Advanced Python for Data Science¶
MSc Artificial Intelligence & Business Analytics,
Toulouse Business School
Objectives¶
Acquiring the Python tools necessary to design a data product MVP in order to quickly test a business opportunity
- Streamlit, a framework allowing to turn data script into shareable web app in minutes
- sqlalchemy, A Python SQL toolkit.
- requests, an elegant and simple HTTP library.
Part #1¶
Objectives of the Part:
- Setup the developping environment
- Get our first data app up and running
> mkdir advanced_python
> cd advanced_python
> mkdir streamlit_apps
> mkdir data
> cd data
# copy data and source code from Campus
> cd ..
Check version of Python and pip¶
Should resp. be 3.6+ and 20.0+
# checking version of Python and pip. Should resp. be 3.6+ and 20.0+
> python --version
> pip --version
Installing the libraries¶
# Streamlit
# Command to run in a Terminal:
> pip install streamlit
> pip install pandas matplotlib seaborn
# to run in Jupyter cell only!
> !pip install streamlit
> !pip install pandas matplotlib seaborn
# requests
# In a Terminal
> pip install requests
# In Jupyter
> !pip install requests
# sqlalchemy
# In a Terminal
> pip install SQLAlchemy
# In Jupyter
>!pip install SQLAlchemy
Streamlit¶
Streamlit is a Python library that turns data scripts into shareable web apps in minutes.
No HTML, CSS, Javascript experience required.
Hello World!¶
import streamlit as st
st.write(
"""
# My first app
Hello *World*!
"""
)
First app -- load data¶
st.write(
"""
# My first app
Tweet sentiment!
"""
)
df_tweet = pd.read_csv('../../data/tweet-sentiment-withDay.csv')
st.write(df_tweet)
Debugging Streamlit apps¶
We have two solutions for debugging our apps:
- Develop in Streamlit and use
st.write()as a debugger (similar to usingprint()in a regular Python script)
- Explore in Jupyter and then copy to Streamlit
Exercice¶
- Put the part of the script loading the data into a separate function.
Data manipulation and user input¶
Streamlit has several features allowing user to interact with our app.
Let's go and add a selectboxto our app:
users_list = get_users(df_tweet)
selected_user = st.selectbox('Choose a user', users_list)
st.write(f'You selected {selected_user}')
Notes: There are 659775 users, make sure to show only part of it for performances
Exercice¶
- Only display the data related to the selected user
- Add the option to select all users
Introduction to caching in Streamlit¶
@st.cache
def some_function():
some commands
Plot data¶
Streamlit charts documentation: https://docs.streamlit.io/library/api-reference/charts
- chart comparison: https://share.streamlit.io/discdiver/data-viz-streamlit/main/app.py
Exercice¶
- Plot the number of message tweeted per day
- Make the graph to show only data from a given user
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import datetime
df = pd.read_csv('../data/tweet-sentiment-withDay.csv')
df['day_utc'] = pd.to_datetime(df['day_utc'], infer_datetime_format=True)
df_timeline = df.groupby('day_utc').count()['target'].reset_index()
fig, ax = plt.subplots()
ax = sns.scatterplot(x = 'day_utc', y = 'target', data=df_timeline)
plt.xlabel('day')
plt.xticks(rotation=45)
plt.xlim(df_timeline['day_utc'].min()-datetime.timedelta(days=1), df_timeline['day_utc'].max()+datetime.timedelta(days=1))
plt.ylabel('number of tweets')
plt.title("Timeline of number of tweets")
plt.show()
Solution
import matplotlib.pyplot as plt
import seaborn as sns
# groupby day
df_timeline = df_tweet.groupby('day_utc').count()['target'].reset_index()
# plot
fig, ax = plt.subplots()
ax = sns.lineplot(x = 'day_utc', y = 'target', data=df_timeline)
plt.xlabel('day')
plt.ylabel('number of tweets')
plt.title("Timeline of number of tweets")
st.pyplot(fig)
Pretty App¶
Streamlit Text elements documentation: https://docs.streamlit.io/library/api-reference/text
Exercice¶
- Add a title, header and subheader to the app
st.title("Advanced Python for Data Science")
st.header("My First app")
st.subheader("A tweet sentiment analysis")
Part #2¶
Objectives of the day:
- CODING BEST PRACTICES
- Clean and modular programming
- Refactor code
- Documentation
- Auto-pep8 and lint
- UNDERSTAND PYTHON ERROR MESSAGES
- HOW TO USE MODULE DOCUMENTATION
- DATA APP
- add plot
- add text
- load data a database
- presentation of SQLAlchemy
- introduction to columns and sidebar
Coding best practices¶
There are 5 topics related to coding best practices:
- Writing clean and modular code
- Refactoring code
- Optimizing code to be more efficient (not covered during this course)
- Writing documentation
- Following PEP8 & Linting
Clean and modular code¶
Clean code -- Code that is readable, simple, and concise. Clean production-quality code is crucial for collaboration and maintainability in software development.
Modular code -- Code that is logically broken up into functions and modules. Modular production-quality code that makes your code more organized, efficient, and reusable.
Module -- A file. Modules allow code to be reused by encapsulating them into files that can be imported into other files.
PEP 8¶
PEP 8 (for Python Extension Proposal) is a set of rules that allows code to be homogenized and best practices to be applied.
Example:
- Should we indent code by 4 spaces or tabs? --> PEP 8 says that indentation is 4 spaces.
- Modules should be imported at the beginning of a script
- Should I use CamelCase or snake_case for naming my functions and variables?
user_list = [1, 2, 3]
for user in user_list:
print(user)
# Naming convention
# == Function ==
def good_function_name():
pass
def BadFunctionNaMe():
pass
# == Variables ==
MY_CONSTANT = 42
my_variable = MY_CONSTANT+2
my_list = [1, 2, 3, 4, 5] # good
my_list = [1,2,3,4,5] # bad
my_list = [1 , 2, 3, 4, 5 ] #bad
my_dict = {
'key1': 'value1',
'key2': 42
}
is_boolean = True
has_boolean = False
is_processed = True
for element in my_list:
print(element)
# bad naming
for i in lst:
print(i)
# == Classes ==
class GoodClassName:
def __init__(self):
self.params = 'foo'
class bad_function_name:
def __init__(self):
self.params = 'foo'
my_var1 = 42
var = 32
my_var1 = my_function(arg1, arg2,
arg3, arg4)
var = 32 + 42 \
+ 52
Writing Clean Code: Nice Whitespace¶
Use whitespace properly.
- Organize your code with consistent indentation: the standard is to use four spaces for each indent. You can make this a default in your text editor.
- Separate sections with blank lines to keep your code well organized and readable.
- Try to limit your lines to around 79 characters, which is the guideline given in the PEP 8 style guide. In many good text editors, there is a setting to display a subtle line that indicates where the 79 character limit is.
# Whitespace usage
# == Operator has whitespace before and after ==
# Good coding practices:
my_variable = 3 + 7
my_text = "mouse"
my_text == my_variable
# Bad coding practices:
my_variable=3+7
my_text="mouse"
my_text== my_variable
# == No whitespace inside (), {}, and [] ==
# Good coding practices:
my_liste[1]
my_dict{"key": 'value'}
my_function(arg)
# Bad coding practices:
my_list[ 1 ]
my_dict{"clé": 'value' }
my_function( arg )
More details¶
Check out the PEP 8 guidelines for code layout
Pop quiz¶
1. Which of the following describes code that is clean? Select all the answers that apply.
- Repetitive
- Simple
- Readable
- Vague
- Concise
Pop quiz -- Answers¶
1. Which of the following describes code that is clean? Select all the answers that apply.
- Repetitive
- Simple
- Readable
- Vague
- Concise
Writing Modular Code: Abstract out logic to improve readability¶
Abstracting out code into a function not only makes it less repetitive, but also improves readability with descriptive function names.
Writing Modular Code: Functions should do one thing¶
Each function you write should be focused on doing one thing. If a function is doing multiple things, it becomes more difficult to generalize and reuse.
Reference¶
A good book on modular programming in Python:
- Modular Programming with Python, by Erik Westra
Pop quiz¶
2. Making your code modular makes it easier to do which of the following things? There may be more than one correct answer
- Reuse your code
- Write less code
- Read your code
- Collaborate on your code
Pop quiz¶
2. Making your code modular makes it easier to do which of the following things? There may be more than one correct answer
- Reuse your code
- Write less code
- Read your code
- Collaborate on your code
Exercice¶
1. Imagine you are writing a program that executes a number of tasks and categorizes each task based on its execution time. Below is a small snippet of this program. Which of the following naming changes could make this code cleaner? There may be more than one correct answer.
t = end_time - start # compute execution time
c = category(t) # get category of task
print('Task Duration: {} seconds, Category: {}'.format(t, c)
- None
- Rename the variable start to
start_timeto make it consistent withend_time. - Rename the variable
ttoexecution_timeto make it more descriptive. - Rename the function
categorytocategory_taskto match the part of speech. - Rename the variable
ctocategoryto make it more descriptive.
Exercice -- Answer¶
1. Imagine you are writing a program that executes a number of tasks and categorizes each task based on its execution time. Below is a small snippet of this program. Which of the following naming changes could make this code cleaner? There may be more than one correct answer.
t = end_time - start # compute execution time
c = category(t) # get category of task
print('Task Duration: {} seconds, Category: {}'.format(t, c)
becomes
execution_time = end_time - start_time
category = categorize_task(execution_time)
print('Task Duration: {} seconds, Category: {}'.format(execution_time, category)
Exercice¶
2. Imagine you analyzed several stocks and calculated the ideal price, or limit price, at which you'd want to buy each stock. You write a program to iterate through your stocks and buy it if the current price is below or equal to the limit price you computed. Otherwise, you put it on a watchlist. Below are three ways of writing this code. Which of the following is the most clean?.
# Choice A
stock_limit_prices = {'LUX': 62.48, 'AAPL': 127.67, 'NVDA': 161.24}
for stock_ticker, stock_limit_price in stock_limit_prices.items():
if stock_limit_price <= get_current_stock_price(stock_ticker):
buy_stock(stock_ticker)
else:
watchlist_stock(stock_ticker)
# Choice B
prices = {'LUX': 62.48, 'AAPL': 127.67, 'NVDA': 161.24}
for ticker, price in prices.items():
if price <= current_price(ticker):
buy(ticker)
else:
watchlist(ticker)
# Choice C
limit_prices = {'LUX': 62.48, 'AAPL': 127.67, 'NVDA': 161.24}
for ticker, limit in limit_prices.items():
if limit <= get_current_price(ticker):
buy(ticker)
else:
watchlist(ticker)
- Choice A
- Choice B
- Choice C
Exercice¶
2. Imagine you analyzed several stocks and calculated the ideal price, or limit price, at which you'd want to buy each stock. You write a program to iterate through your stocks and buy it if the current price is below or equal to the limit price you computed. Otherwise, you put it on a watchlist. Below are three ways of writing this code. Which of the following is the most clean?.
# Choice C
limit_prices = {'LUX': 62.48, 'AAPL': 127.67, 'NVDA': 161.24}
for ticker, limit in limit_prices.items():
if limit <= get_current_price(ticker):
buy(ticker)
else:
watchlist(ticker)
- Choice A
- Choice B
- Choice C
Refactor code¶
Refactoring -- Restructuring your code to improve its internal structure without changing its external functionality. This gives you a chance to clean and modularize your program after you've got it working.
Writing documentation¶
Documentation -- Additional text or illustrated information that comes with or is embedded in the code of software. Documentation is helpful for clarifying complex parts of code, making your code easier to navigate, and quickly conveying how and why different components of your program are used. Several types of documentation can be added at different levels of your program:
- Inline comments - line level
my_var = 42 # this is the ultimate answer
- Docstrings - module and function level
def get_ultimate_aswer(question):
'''This is the awesome function of the universe
Parameters
----------
question: str
Return
------
_: int
'''
return 42
- Project documentation - project level
automating PEP8 & Linting¶
We have two ways to automate clean code:
- pylint -- it is a Python static code analysis tool which looks for programming errors, helps enforcing a coding standard, sniffs for code smells and offers simple refactoring suggestions.
- autopep8 -- automatically formats Python code to conform to the PEP 8 style guide.
pylint script_name.py will provide feedback on updates to make to your code, as well as a score out of 10 that can help you understand which improvements are most important.
autopep8 --in-place --aggressive --aggressive script_name.py will attempt to automatically clean up your code.
> pip install autopep8
> pip install pylint
> pylint first_day.py
> autopep8 --in-place --aggressive --aggressive first_day.py
> pylint first_day.py
Decoding Python error¶
Learn to understand what Python is telling you
import pandas
df = pd.read_csv('../data/tweets-sentiment.csv')
--------------------------------------------------------------------------- FileNotFoundError Traceback (most recent call last) Cell In [3], line 2 1 import pandas ----> 2 df = pd.read_csv('../data/tweets-sentiment.csv') File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/util/_decorators.py:211, in deprecate_kwarg.<locals>._deprecate_kwarg.<locals>.wrapper(*args, **kwargs) 209 else: 210 kwargs[new_arg_name] = new_arg_value --> 211 return func(*args, **kwargs) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/util/_decorators.py:317, in deprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper(*args, **kwargs) 311 if len(args) > num_allow_args: 312 warnings.warn( 313 msg.format(arguments=arguments), 314 FutureWarning, 315 stacklevel=find_stack_level(inspect.currentframe()), 316 ) --> 317 return func(*args, **kwargs) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:950, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, error_bad_lines, warn_bad_lines, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options) 935 kwds_defaults = _refine_defaults_read( 936 dialect, 937 delimiter, (...) 946 defaults={"delimiter": ","}, 947 ) 948 kwds.update(kwds_defaults) --> 950 return _read(filepath_or_buffer, kwds) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:605, in _read(filepath_or_buffer, kwds) 602 _validate_names(kwds.get("names", None)) 604 # Create the parser. --> 605 parser = TextFileReader(filepath_or_buffer, **kwds) 607 if chunksize or iterator: 608 return parser File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:1442, in TextFileReader.__init__(self, f, engine, **kwds) 1439 self.options["has_index_names"] = kwds["has_index_names"] 1441 self.handles: IOHandles | None = None -> 1442 self._engine = self._make_engine(f, self.engine) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:1729, in TextFileReader._make_engine(self, f, engine) 1727 is_text = False 1728 mode = "rb" -> 1729 self.handles = get_handle( 1730 f, 1731 mode, 1732 encoding=self.options.get("encoding", None), 1733 compression=self.options.get("compression", None), 1734 memory_map=self.options.get("memory_map", False), 1735 is_text=is_text, 1736 errors=self.options.get("encoding_errors", "strict"), 1737 storage_options=self.options.get("storage_options", None), 1738 ) 1739 assert self.handles is not None 1740 f = self.handles.handle File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/common.py:857, in get_handle(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options) 852 elif isinstance(handle, str): 853 # Check whether the filename is to be opened in binary mode. 854 # Binary mode does not support 'encoding' and 'newline'. 855 if ioargs.encoding and "b" not in ioargs.mode: 856 # Encoding --> 857 handle = open( 858 handle, 859 ioargs.mode, 860 encoding=ioargs.encoding, 861 errors=errors, 862 newline="", 863 ) 864 else: 865 # Binary mode 866 handle = open(handle, ioargs.mode) FileNotFoundError: [Errno 2] No such file or directory: '../data/tweets-sentiment.csv'
import pandas as pd
df = pd.read_csv('../data/tweet-sentiment.csv')
df.head()
--------------------------------------------------------------------------- FileNotFoundError Traceback (most recent call last) Cell In [4], line 2 1 import pandas as pd ----> 2 df = pd.read_csv('../data/tweet-sentiment.csv') 3 df.head() File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/util/_decorators.py:211, in deprecate_kwarg.<locals>._deprecate_kwarg.<locals>.wrapper(*args, **kwargs) 209 else: 210 kwargs[new_arg_name] = new_arg_value --> 211 return func(*args, **kwargs) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/util/_decorators.py:317, in deprecate_nonkeyword_arguments.<locals>.decorate.<locals>.wrapper(*args, **kwargs) 311 if len(args) > num_allow_args: 312 warnings.warn( 313 msg.format(arguments=arguments), 314 FutureWarning, 315 stacklevel=find_stack_level(inspect.currentframe()), 316 ) --> 317 return func(*args, **kwargs) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:950, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, error_bad_lines, warn_bad_lines, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options) 935 kwds_defaults = _refine_defaults_read( 936 dialect, 937 delimiter, (...) 946 defaults={"delimiter": ","}, 947 ) 948 kwds.update(kwds_defaults) --> 950 return _read(filepath_or_buffer, kwds) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:605, in _read(filepath_or_buffer, kwds) 602 _validate_names(kwds.get("names", None)) 604 # Create the parser. --> 605 parser = TextFileReader(filepath_or_buffer, **kwds) 607 if chunksize or iterator: 608 return parser File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:1442, in TextFileReader.__init__(self, f, engine, **kwds) 1439 self.options["has_index_names"] = kwds["has_index_names"] 1441 self.handles: IOHandles | None = None -> 1442 self._engine = self._make_engine(f, self.engine) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/parsers/readers.py:1729, in TextFileReader._make_engine(self, f, engine) 1727 is_text = False 1728 mode = "rb" -> 1729 self.handles = get_handle( 1730 f, 1731 mode, 1732 encoding=self.options.get("encoding", None), 1733 compression=self.options.get("compression", None), 1734 memory_map=self.options.get("memory_map", False), 1735 is_text=is_text, 1736 errors=self.options.get("encoding_errors", "strict"), 1737 storage_options=self.options.get("storage_options", None), 1738 ) 1739 assert self.handles is not None 1740 f = self.handles.handle File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/pandas/io/common.py:857, in get_handle(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options) 852 elif isinstance(handle, str): 853 # Check whether the filename is to be opened in binary mode. 854 # Binary mode does not support 'encoding' and 'newline'. 855 if ioargs.encoding and "b" not in ioargs.mode: 856 # Encoding --> 857 handle = open( 858 handle, 859 ioargs.mode, 860 encoding=ioargs.encoding, 861 errors=errors, 862 newline="", 863 ) 864 else: 865 # Binary mode 866 handle = open(handle, ioargs.mode) FileNotFoundError: [Errno 2] No such file or directory: '../data/tweet-sentiment.csv'
!%pwd
/Volumes/trappist1/missions/tbs/2022-2023/PYTHON-102/notebooks
import pandas as pd
fname = "/Volumes/trappist1/missions/tbs/2022-2023/PYTHON-102/campus/ue33-parttime/data/tweet-sentiment-withDay.csv"
df = pd.read_csv(fname)
df.head()
| target | id | date | flag | user | text | date_utc | day_utc | |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 1467810369 | Mon Apr 06 22:19:45 PDT 2009 | NO_QUERY | _TheSpecialOne_ | @switchfoot http://twitpic.com/2y1zl - Awww, t... | 2009-04-07 06:12:45+00:00 | 2009-04-07 |
| 1 | 0 | 1467810672 | Mon Apr 06 22:19:49 PDT 2009 | NO_QUERY | scotthamilton | is upset that he can't update his Facebook by ... | 2009-04-07 06:12:49+00:00 | 2009-04-07 |
| 2 | 0 | 1467810917 | Mon Apr 06 22:19:53 PDT 2009 | NO_QUERY | mattycus | @Kenichan I dived many times for the ball. Man... | 2009-04-07 06:12:53+00:00 | 2009-04-07 |
| 3 | 0 | 1467811184 | Mon Apr 06 22:19:57 PDT 2009 | NO_QUERY | ElleCTF | my whole body feels itchy and like its on fire | 2009-04-07 06:12:57+00:00 | 2009-04-07 |
| 4 | 0 | 1467811193 | Mon Apr 06 22:19:57 PDT 2009 | NO_QUERY | Karoli | @nationwideclass no, it's not behaving at all.... | 2009-04-07 06:12:57+00:00 | 2009-04-07 |
def function_with_error():
my_variable = 42
my_second_variable = 24
print(my_second_variable)
function_with_error()
Cell In [7], line 3 my_second_variable = 24 ^ IndentationError: unexpected indent
def function_with_error():
my_variable = 42
my_second_variable = 24
print(my_second_variable)
function_with_error()
24
SQLAlchemy¶
provides a nice “Pythonic” way of interacting with databases and integrate well with pandas
To install the module, run:
$ pip install SQLAlchemy
# Using SQLAlchemy with Pandas
import sqlalchemy as sa
import pandas as pd
# Creating the engine | defining which type of the database we use
engine = sa.create_engine("sqlite:////Volumes/trappist1/missions/tbs/2022-2023/PYTHON-102/campus/ue33-parttime/data/tweet-sentiment-withDay.db", echo=False)
# windows
#engine = sa.create_engine("sqlite:///C:/Users/username/<path-to-file/tweet-sentiment.db", echo=False)
# macOS/linux
#engine = sa.create_engine("sqlite:///Users/username/<path-to-file/tweet-sentiment.db", echo=False)
# another example of connection
# engine = sa.create_engine("postgresql://username:password@ip-address:port/database-name")
sa_connection = engine.connect()
sa_connection
<sqlalchemy.engine.base.Connection at 0x7fc6b7386970>
# Getting list of tables availables in database
print(engine.table_names())
['tweets']
/var/folders/fc/ck893lx10jlfdzdx9785rsf00000gn/T/ipykernel_13847/4030562895.py:2: SADeprecationWarning: The Engine.table_names() method is deprecated and will be removed in a future release. Please refer to Inspector.get_table_names(). (deprecated since: 1.4) print(engine.table_names())
# Extracting the data into a Pandas DataFrame
sql_query = "SELECT * FROM tweets"
tweets = pd.read_sql(sql_query, sa_connection)
tweets.head()
| target | id | date | flag | user | text | date_utc | day_utc | |
|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 1467810369 | Mon Apr 06 22:19:45 PDT 2009 | NO_QUERY | _TheSpecialOne_ | @switchfoot http://twitpic.com/2y1zl - Awww, t... | 2009-04-07 06:12:45+00:00 | 2009-04-07 |
| 1 | 0 | 1467810672 | Mon Apr 06 22:19:49 PDT 2009 | NO_QUERY | scotthamilton | is upset that he can't update his Facebook by ... | 2009-04-07 06:12:49+00:00 | 2009-04-07 |
| 2 | 0 | 1467810917 | Mon Apr 06 22:19:53 PDT 2009 | NO_QUERY | mattycus | @Kenichan I dived many times for the ball. Man... | 2009-04-07 06:12:53+00:00 | 2009-04-07 |
| 3 | 0 | 1467811184 | Mon Apr 06 22:19:57 PDT 2009 | NO_QUERY | ElleCTF | my whole body feels itchy and like its on fire | 2009-04-07 06:12:57+00:00 | 2009-04-07 |
| 4 | 0 | 1467811193 | Mon Apr 06 22:19:57 PDT 2009 | NO_QUERY | Karoli | @nationwideclass no, it's not behaving at all.... | 2009-04-07 06:12:57+00:00 | 2009-04-07 |
Preliminary data analysis¶
# Number of rows
sql_query = """
SELECT COUNT(*)
FROM tweets
"""
pd.read_sql(sql_query, sa_connection)
| COUNT(*) | |
|---|---|
| 0 | 1600000 |
The dataset contains 1600000 tweets extracted using the Twitter API.
# Distribution of tweets
sql_query = """
SELECT target, COUNT(*) as nb_per_sentiment
FROM tweets
GROUP BY target
"""
pd.read_sql(sql_query, sa_connection)
SELECT target, COUNT(*) as nb_per_sentiment
FROM tweets
GROUP BY target
| target | nb_per_sentiment | |
|---|---|---|
| 0 | 0 | 800000 |
| 1 | 4 | 800000 |
Each tweet has been annotated:
- 0: Negative
- 4: Positive
The dataset is evently distributed between these two annotations.
# Distribution of tweets per user
sql_query = """
SELECT user, COUNT(target) as nb_tweets
FROM tweets
GROUP BY user
LIMIT 10
"""
pd.read_sql(sql_query, sa_connection)
| user | nb_tweets | |
|---|---|---|
| 0 | 000catnap000 | 6 |
| 1 | 000matthewkelly | 1 |
| 2 | 000yea000 | 1 |
| 3 | 0010x0010 | 1 |
| 4 | 001BabyGirl | 2 |
| 5 | 001trish | 1 |
| 6 | 006jazzy | 1 |
| 7 | 007LouiseOB | 1 |
| 8 | 007_Chris_007 | 6 |
| 9 | 007buddha | 1 |
# Distribution of tweets per user -- Ordered
sql_query = """
SELECT user, COUNT(target) as nb_tweets
FROM tweets
GROUP BY user
ORDER BY nb_tweets DESC --ASC
LIMIT 10
"""
pd.read_sql(sql_query, sa_connection)
| user | nb_tweets | |
|---|---|---|
| 0 | lost_dog | 549 |
| 1 | webwoke | 345 |
| 2 | tweetpet | 310 |
| 3 | SallytheShizzle | 281 |
| 4 | VioletsCRUK | 279 |
| 5 | mcraddictal | 276 |
| 6 | tsarnick | 248 |
| 7 | what_bugs_u | 246 |
| 8 | Karen230683 | 238 |
| 9 | DarkPiano | 236 |
Exercice¶
- Load data from sqlite3 database instead of csv file
- Show the distribution of tweets per sentiment
import sqlalchemy as sa
import pandas as pd
# Creating the engine | defining which type of the database we use
engine = sa.create_engine("sqlite:////Users/samiadrappeau/Documents/TBS/PYTHON-102/tweet-sentiment-withDay.db", echo=False)
sa_connection = engine.connect()
sql_query = """
SELECT *
FROM tweets
"""
tweets = pd.read_sql(sql_query, sa_connection)
tweets.head()
--------------------------------------------------------------------------- OperationalError Traceback (most recent call last) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/base.py:3361, in Engine._wrap_pool_connect(self, fn, connection) 3360 try: -> 3361 return fn() 3362 except dialect.dbapi.Error as e: File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:320, in Pool.connect(self) 313 """Return a DBAPI connection from the pool. 314 315 The connection is instrumented such that when its (...) 318 319 """ --> 320 return _ConnectionFairy._checkout(self) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:884, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy) 883 if not fairy: --> 884 fairy = _ConnectionRecord.checkout(pool) 886 fairy._pool = pool File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:486, in _ConnectionRecord.checkout(cls, pool) 484 @classmethod 485 def checkout(cls, pool): --> 486 rec = pool._do_get() 487 try: File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/impl.py:256, in NullPool._do_get(self) 255 def _do_get(self): --> 256 return self._create_connection() File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:266, in Pool._create_connection(self) 264 """Called by subclasses to create a new ConnectionRecord.""" --> 266 return _ConnectionRecord(self) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:381, in _ConnectionRecord.__init__(self, pool, connect) 380 if connect: --> 381 self.__connect() 382 self.finalize_callback = deque() File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:678, in _ConnectionRecord.__connect(self) 677 with util.safe_reraise(): --> 678 pool.logger.debug("Error on connect(): %s", e) 679 else: 680 # in SQLAlchemy 1.4 the first_connect event is not used by 681 # the engine, so this will usually not be set File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py:70, in safe_reraise.__exit__(self, type_, value, traceback) 69 if not self.warn_only: ---> 70 compat.raise_( 71 exc_value, 72 with_traceback=exc_tb, 73 ) 74 else: File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/util/compat.py:208, in raise_(***failed resolving arguments***) 207 try: --> 208 raise exception 209 finally: 210 # credit to 211 # https://cosmicpercolator.com/2016/01/13/exception-leaks-in-python-2-and-3/ 212 # as the __traceback__ object creates a cycle File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:673, in _ConnectionRecord.__connect(self) 672 self.starttime = time.time() --> 673 self.dbapi_connection = connection = pool._invoke_creator(self) 674 pool.logger.debug("Created new connection %r", connection) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/create.py:578, in create_engine.<locals>.connect(connection_record) 577 return connection --> 578 return dialect.connect(*cargs, **cparams) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/default.py:598, in DefaultDialect.connect(self, *cargs, **cparams) 596 def connect(self, *cargs, **cparams): 597 # inherits the docstring from interfaces.Dialect.connect --> 598 return self.dbapi.connect(*cargs, **cparams) OperationalError: unable to open database file The above exception was the direct cause of the following exception: OperationalError Traceback (most recent call last) Cell In [4], line 6 4 # Creating the engine | defining which type of the database we use 5 engine = sa.create_engine("sqlite:////Users/samiadrappeau/Documents/TBS/PYTHON-102/tweet-sentiment-withDay.db", echo=False) ----> 6 sa_connection = engine.connect() 8 sql_query = """ 9 SELECT * 10 FROM tweets 11 """ 13 tweets = pd.read_sql(sql_query, sa_connection) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/base.py:3315, in Engine.connect(self, close_with_result) 3300 def connect(self, close_with_result=False): 3301 """Return a new :class:`_engine.Connection` object. 3302 3303 The :class:`_engine.Connection` object is a facade that uses a DBAPI (...) 3312 3313 """ -> 3315 return self._connection_cls(self, close_with_result=close_with_result) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/base.py:96, in Connection.__init__(self, engine, connection, close_with_result, _branch_from, _execution_options, _dispatch, _has_events, _allow_revalidate) 91 self._has_events = _branch_from._has_events 92 else: 93 self._dbapi_connection = ( 94 connection 95 if connection is not None ---> 96 else engine.raw_connection() 97 ) 99 self._transaction = self._nested_transaction = None 100 self.__savepoint_seq = 0 File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/base.py:3394, in Engine.raw_connection(self, _connection) 3372 def raw_connection(self, _connection=None): 3373 """Return a "raw" DBAPI connection from the connection pool. 3374 3375 The returned object is a proxied version of the DBAPI (...) 3392 3393 """ -> 3394 return self._wrap_pool_connect(self.pool.connect, _connection) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/base.py:3364, in Engine._wrap_pool_connect(self, fn, connection) 3362 except dialect.dbapi.Error as e: 3363 if connection is None: -> 3364 Connection._handle_dbapi_exception_noconnection( 3365 e, dialect, self 3366 ) 3367 else: 3368 util.raise_( 3369 sys.exc_info()[1], with_traceback=sys.exc_info()[2] 3370 ) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/base.py:2198, in Connection._handle_dbapi_exception_noconnection(cls, e, dialect, engine) 2196 util.raise_(newraise, with_traceback=exc_info[2], from_=e) 2197 elif should_wrap: -> 2198 util.raise_( 2199 sqlalchemy_exception, with_traceback=exc_info[2], from_=e 2200 ) 2201 else: 2202 util.raise_(exc_info[1], with_traceback=exc_info[2]) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/util/compat.py:208, in raise_(***failed resolving arguments***) 205 exception.__cause__ = replace_context 207 try: --> 208 raise exception 209 finally: 210 # credit to 211 # https://cosmicpercolator.com/2016/01/13/exception-leaks-in-python-2-and-3/ 212 # as the __traceback__ object creates a cycle 213 del exception, replace_context, from_, with_traceback File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/base.py:3361, in Engine._wrap_pool_connect(self, fn, connection) 3359 dialect = self.dialect 3360 try: -> 3361 return fn() 3362 except dialect.dbapi.Error as e: 3363 if connection is None: File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:320, in Pool.connect(self) 312 def connect(self): 313 """Return a DBAPI connection from the pool. 314 315 The connection is instrumented such that when its (...) 318 319 """ --> 320 return _ConnectionFairy._checkout(self) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:884, in _ConnectionFairy._checkout(cls, pool, threadconns, fairy) 881 @classmethod 882 def _checkout(cls, pool, threadconns=None, fairy=None): 883 if not fairy: --> 884 fairy = _ConnectionRecord.checkout(pool) 886 fairy._pool = pool 887 fairy._counter = 0 File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:486, in _ConnectionRecord.checkout(cls, pool) 484 @classmethod 485 def checkout(cls, pool): --> 486 rec = pool._do_get() 487 try: 488 dbapi_connection = rec.get_connection() File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/impl.py:256, in NullPool._do_get(self) 255 def _do_get(self): --> 256 return self._create_connection() File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:266, in Pool._create_connection(self) 263 def _create_connection(self): 264 """Called by subclasses to create a new ConnectionRecord.""" --> 266 return _ConnectionRecord(self) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:381, in _ConnectionRecord.__init__(self, pool, connect) 379 self.__pool = pool 380 if connect: --> 381 self.__connect() 382 self.finalize_callback = deque() File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:678, in _ConnectionRecord.__connect(self) 676 except Exception as e: 677 with util.safe_reraise(): --> 678 pool.logger.debug("Error on connect(): %s", e) 679 else: 680 # in SQLAlchemy 1.4 the first_connect event is not used by 681 # the engine, so this will usually not be set 682 if pool.dispatch.first_connect: File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py:70, in safe_reraise.__exit__(self, type_, value, traceback) 68 self._exc_info = None # remove potential circular references 69 if not self.warn_only: ---> 70 compat.raise_( 71 exc_value, 72 with_traceback=exc_tb, 73 ) 74 else: 75 if not compat.py3k and self._exc_info and self._exc_info[1]: 76 # emulate Py3K's behavior of telling us when an exception 77 # occurs in an exception handler. File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/util/compat.py:208, in raise_(***failed resolving arguments***) 205 exception.__cause__ = replace_context 207 try: --> 208 raise exception 209 finally: 210 # credit to 211 # https://cosmicpercolator.com/2016/01/13/exception-leaks-in-python-2-and-3/ 212 # as the __traceback__ object creates a cycle 213 del exception, replace_context, from_, with_traceback File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/pool/base.py:673, in _ConnectionRecord.__connect(self) 671 try: 672 self.starttime = time.time() --> 673 self.dbapi_connection = connection = pool._invoke_creator(self) 674 pool.logger.debug("Created new connection %r", connection) 675 self.fresh = True File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/create.py:578, in create_engine.<locals>.connect(connection_record) 576 if connection is not None: 577 return connection --> 578 return dialect.connect(*cargs, **cparams) File ~/anaconda3/envs/datascience/lib/python3.8/site-packages/sqlalchemy/engine/default.py:598, in DefaultDialect.connect(self, *cargs, **cparams) 596 def connect(self, *cargs, **cparams): 597 # inherits the docstring from interfaces.Dialect.connect --> 598 return self.dbapi.connect(*cargs, **cparams) OperationalError: (sqlite3.OperationalError) unable to open database file (Background on this error at: https://sqlalche.me/e/14/e3q8)
Beautifying Streamlit app¶
Sidebar¶
Hand-on: Find in Streamlit documentation how to create a sidebar in Streamlit
Columns¶
Hand-on: Find in Streamlit documentation how to create columns in Streamlit
Exercice¶
- Place all data and distribution of tweets per sentiment in two separate screens
- Make side-by-side word-cloud per sentiment type
Part #3¶
Objectives of the day:
- DATA APP
- Write a REST API
- presentation of Flask
- Interact with a REST API
- presentation of requests
- Write a REST API
Flask¶
Flask is a web framework, it's a Python module that lets you develop web applications easily.
- documentation: https://flask.palletsprojects.com/en/2.0.x/#api-reference
Hello World Flask server¶
Install FLASK
$ pip install flask
# ou
$ conda install -c anaconda flask
Open a new file flask-hello_world.py and copy the following code:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
Then save it.
Run the Hello World Flask server¶
To run your web application, you’ll first tell Flask where to find the application (the hello-flask.py file in your case) with the FLASK_APP environment variable.
Please execute the following command in your terminal, making sure you are located where the script is:
> export FLASK_APP=hello-flask
> export FLASK_ENV=development
#for windows machine
# > set FLASK_APP=hello-flask
# > set FLASK_ENV=development
> flask run
You should see something like this:
Output
* Serving Flask app "hello" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger PIN: 813-894-335
Bravo!¶
You are running your first REST API!
Install first the folllowing modules:
$ pip install textblob
# ou
$ conda install -c conda-forge textblob
Now, open a new file model_server.py and copy the following code into it:
from flask import Flask, jsonify, request
from textblob import TextBlob
app = Flask(__name__)
# Add all the routes you want below
@app.route("/predict", methods=['GET'])
def get_prediction():
text = request.args.get('text')
testimonial = TextBlob(text).sentiment.polarity
return jsonify(polarity=testimonial)
if __name__ == '__main__':
app.run()
Then save it.
Now, stop the previous running Flask server (with Ctrl-C), and execute the following commands:
> export FLASK_APP=model_server
> flask run
Your first Machine Learning server is up and running!
Now, open your favorite browser and enter the following URL:
http://127.0.0.1:5000/predict?text="this is awesome!"
Requests¶
- documentation: https://docs.python-requests.org/en/latest/
Requests is an elegant and simple Python library built to handle HTTP requests in python easily.
But what is a HTTP request?
HTTP is a set of protocols designed to enable communication between clients and servers.
A client is typically a local computer or device similar to what you are using to view this page.
A HTTP request is the message sent (or received) from your local computer to a web server hosting, typically hosting a website.
For example, when you go to any internet website from your browser, the browser is sending a HTTP request and receives an appropriate ‘response’ from the host server.
Requests is an easy-to-use library with a lot of features ranging from passing additional parameters in URLs, sending custom headers, SSL Verification, processing the received response etc.
Most commenly-used HTTP methods to request:¶
- GET (=read operation)
- POST (=create operation)
- PUT (=update operation)
- PATCH (=update operation)
- DELETE (=delete operation)
What is a GET and POST request?¶
A GET request is used to request data from a specific server. It is the most common type of request. This is synonymous to you visiting the homepage of a website from your browser.
Another common type of request is the POST request, which is used to send data to a host server for further processing, like, to update a resource, such as a database. What is this synonymous to in real world? For example, most data that you submit through forms in various websites is sent and processed as a POST request.
GET Method¶
import requests
response = requests.get('https://www.python.org/')
print(response)
<Response [200]>
STATUS Code¶
Status codes are issued by a server in response to a client’s request made to the server.
Use the r.status_code command to return the status code for your request.
print(response.status_code)
200
- A response of 200 means Success.
- A response of 300 means Redirected.
- A response of 400 means Client Error.
- A response of 404 means Page Not Found Error.
- A response of 500 means Server Error.
In general, any status code less than 400 means, the request was processed successfully. If it is 400 and above, some sort of error occurred.
if r.status_code == 200:
print("It's a great Success!!")
elif r.status_code == 404:
print("Page not found")
It's a great Success!!
Contents of the Response object¶
dir(r) function is used to get details about what all useful information we can get from the data we retrived.
r_list = []
for c in dir(response):
if not c.startswith("_"):
r_list.append(c)
print(r_list)
['apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']
[c for c in dir(response) if not c.startswith("_")]
['apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']
print(response.url)
https://www.python.org/
# Raw Content
print(response.content[:800])
b'<!doctype html>\n<!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"> <![endif]-->\n<!--[if IE 7]> <html class="no-js ie7 lt-ie8 lt-ie9"> <![endif]-->\n<!--[if IE 8]> <html class="no-js ie8 lt-ie9"> <![endif]-->\n<!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"> <!--<![endif]-->\n\n<head>\n <!-- Google tag (gtag.js) -->\n <script async src="https://www.googletagmanager.com/gtag/js?id=G-TF35YF9CVH"></script>\n <script>\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag(\'js\', new Date());\n gtag(\'config\', \'G-TF35YF9CVH\');\n </script>\n\n <meta charset="utf-8">\n <meta http-equiv="X-UA-Compatible" content="IE=edge">\n\n <link rel="prefetch" href="//ajax.googleap'
# Content as text
print(response.text[:800])
<!doctype html>
<!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"> <![endif]-->
<!--[if IE 7]> <html class="no-js ie7 lt-ie8 lt-ie9"> <![endif]-->
<!--[if IE 8]> <html class="no-js ie8 lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"> <!--<![endif]-->
<head>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-TF35YF9CVH"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-TF35YF9CVH');
</script>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="prefetch" href="//ajax.googleap
import requests
# This is the REST API we just developed earlier
sample_text = 'This is horrible!'
r = requests.get(f"http://127.0.0.1:5000/predict?text={sample_text}")
print(r.content)
print(r.text)
b'{"polarity":-1.0}\n'
{"polarity":-1.0}
print(r.json())
{'polarity': -1.0}
print(r.json()['polarity'])
-1.0
import requests
sample_text = 'This is awesome!'
r = requests.get(f"http://127.0.0.1:5000/predict?text={sample_text}")
print(r.json()['polarity'])
1.0
import requests
sample_text = 'This is ok-ish.'
r = requests.get(f"http://127.0.0.1:5000/predict?text={sample_text}")
print(r.json()['polarity'])
0.0
import requests
r = requests.get('https://api.github.com/events')
print(r.json())
[{'id': '20038546522', 'type': 'CreateEvent', 'actor': {'id': 90335716, 'login': 'dub6ix', 'display_login': 'dub6ix', 'gravatar_id': '', 'url': 'https://api.github.com/users/dub6ix', 'avatar_url': 'https://avatars.githubusercontent.com/u/90335716?'}, 'repo': {'id': 454172086, 'name': 'nuggxyz/dotnugg-grammar', 'url': 'https://api.github.com/repos/nuggxyz/dotnugg-grammar'}, 'payload': {'ref': '0.1.8', 'ref_type': 'tag', 'master_branch': 'main', 'description': None, 'pusher_type': 'user'}, 'public': True, 'created_at': '2022-02-02T14:23:30Z', 'org': {'id': 93823471, 'login': 'nuggxyz', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/nuggxyz', 'avatar_url': 'https://avatars.githubusercontent.com/u/93823471?'}}, {'id': '20038546691', 'type': 'CreateEvent', 'actor': {'id': 10166338, 'login': 'akashtalole', 'display_login': 'akashtalole', 'gravatar_id': '', 'url': 'https://api.github.com/users/akashtalole', 'avatar_url': 'https://avatars.githubusercontent.com/u/10166338?'}, 'repo': {'id': 454800011, 'name': 'akashtalole/node-red-contrib-thingsboard-rest-api-auth', 'url': 'https://api.github.com/repos/akashtalole/node-red-contrib-thingsboard-rest-api-auth'}, 'payload': {'ref': 'main', 'ref_type': 'branch', 'master_branch': 'main', 'description': 'node-red-contrib-thingsboard-rest-api-auth', 'pusher_type': 'user'}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546603', 'type': 'IssuesEvent', 'actor': {'id': 1526295, 'login': 'sldblog', 'display_login': 'sldblog', 'gravatar_id': '', 'url': 'https://api.github.com/users/sldblog', 'avatar_url': 'https://avatars.githubusercontent.com/u/1526295?'}, 'repo': {'id': 312544484, 'name': 'ministryofjustice/hmpps-interventions-ui', 'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui'}, 'payload': {'action': 'closed', 'issue': {'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197', 'repository_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui', 'labels_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/labels{/name}', 'comments_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/comments', 'events_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/events', 'html_url': 'https://github.com/ministryofjustice/hmpps-interventions-ui/issues/1197', 'id': 1117364167, 'node_id': 'I_kwDOEqEM5M5CmZ_H', 'number': 1197, 'title': 'A branch protection setting is not enabled: Include administrators', 'user': {'login': 'AntonyBishop', 'id': 36888942, 'node_id': 'MDQ6VXNlcjM2ODg4OTQy', 'avatar_url': 'https://avatars.githubusercontent.com/u/36888942?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/AntonyBishop', 'html_url': 'https://github.com/AntonyBishop', 'followers_url': 'https://api.github.com/users/AntonyBishop/followers', 'following_url': 'https://api.github.com/users/AntonyBishop/following{/other_user}', 'gists_url': 'https://api.github.com/users/AntonyBishop/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/AntonyBishop/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/AntonyBishop/subscriptions', 'organizations_url': 'https://api.github.com/users/AntonyBishop/orgs', 'repos_url': 'https://api.github.com/users/AntonyBishop/repos', 'events_url': 'https://api.github.com/users/AntonyBishop/events{/privacy}', 'received_events_url': 'https://api.github.com/users/AntonyBishop/received_events', 'type': 'User', 'site_admin': False}, 'labels': [], 'state': 'closed', 'locked': False, 'assignee': None, 'assignees': [], 'milestone': None, 'comments': 1, 'created_at': '2022-01-28T12:45:33Z', 'updated_at': '2022-02-02T14:23:29Z', 'closed_at': '2022-02-02T14:23:29Z', 'author_association': 'NONE', 'active_lock_reason': None, 'body': 'Hi there\nThe default branch protection setting called Include administrators is not enabled for this repository\nSee repository settings/Branches/Branch protection rules\nEither add a new Branch protection rule or edit the existing branch protection rule and select the Include administrators option\nThis will enable the branch protection rules to admin uses as well\nSee the repository standards: https://github.com/ministryofjustice/github-repository-standards\nSee the report: https://operations-engineering-reports.cloud-platform.service.justice.gov.uk/github_repositories\nPlease contact Operations Engineering on Slack #ask-operations-engineering, if you need any assistance\n', 'reactions': {'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/reactions', 'total_count': 0, '+1': 0, '-1': 0, 'laugh': 0, 'hooray': 0, 'confused': 0, 'heart': 0, 'rocket': 0, 'eyes': 0}, 'timeline_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/timeline', 'performed_via_github_app': None}}, 'public': True, 'created_at': '2022-02-02T14:23:31Z', 'org': {'id': 2203574, 'login': 'ministryofjustice', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/ministryofjustice', 'avatar_url': 'https://avatars.githubusercontent.com/u/2203574?'}}, {'id': '20038546684', 'type': 'PushEvent', 'actor': {'id': 36798399, 'login': 'Ishoshot', 'display_login': 'Ishoshot', 'gravatar_id': '', 'url': 'https://api.github.com/users/Ishoshot', 'avatar_url': 'https://avatars.githubusercontent.com/u/36798399?'}, 'repo': {'id': 452715731, 'name': 'Ishoshot/morebitcoin', 'url': 'https://api.github.com/repos/Ishoshot/morebitcoin'}, 'payload': {'push_id': 8993439111, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/master', 'head': '0a0e70acab5f3111496ec17b9b67e6224f3c3930', 'before': '767048afe423fc336f8f667c16f3126b9bd083de', 'commits': [{'sha': '0a0e70acab5f3111496ec17b9b67e6224f3c3930', 'author': {'email': 'ishoshot@gmail.com', 'name': 'ishoshot'}, 'message': 'Dashboard ChartData bug', 'distinct': True, 'url': 'https://api.github.com/repos/Ishoshot/morebitcoin/commits/0a0e70acab5f3111496ec17b9b67e6224f3c3930'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546503', 'type': 'PushEvent', 'actor': {'id': 14362322, 'login': 'luchoaglp', 'display_login': 'luchoaglp', 'gravatar_id': '', 'url': 'https://api.github.com/users/luchoaglp', 'avatar_url': 'https://avatars.githubusercontent.com/u/14362322?'}, 'repo': {'id': 453433596, 'name': 'luchoaglp/creditoazteca', 'url': 'https://api.github.com/repos/luchoaglp/creditoazteca'}, 'payload': {'push_id': 8993439005, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/main', 'head': '10dcb266af7bb2039d01f6f54e649ccde4a9cddf', 'before': 'c23de70260cf64e36ad5d0bb173f87852b23eaa6', 'commits': [{'sha': '10dcb266af7bb2039d01f6f54e649ccde4a9cddf', 'author': {'email': 'lucho_aglp@hotmail.com', 'name': 'luchoaglp'}, 'message': 'Update', 'distinct': True, 'url': 'https://api.github.com/repos/luchoaglp/creditoazteca/commits/10dcb266af7bb2039d01f6f54e649ccde4a9cddf'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z'}, {'id': '20038546704', 'type': 'PushEvent', 'actor': {'id': 42819689, 'login': 'whitesource-bolt-for-github[bot]', 'display_login': 'whitesource-bolt-for-github', 'gravatar_id': '', 'url': 'https://api.github.com/users/whitesource-bolt-for-github[bot]', 'avatar_url': 'https://avatars.githubusercontent.com/u/42819689?'}, 'repo': {'id': 454805278, 'name': 'LaudateCorpus1/haul', 'url': 'https://api.github.com/repos/LaudateCorpus1/haul'}, 'payload': {'push_id': 8993439123, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/whitesource/configure', 'head': 'f1ec06f177d707ae8191f423a3da9bd8b9e8854e', 'before': 'bfc5578b541d935ebc58356ae20e15a726c5284d', 'commits': [{'sha': 'f1ec06f177d707ae8191f423a3da9bd8b9e8854e', 'author': {'email': '42819689+whitesource-bolt-for-github[bot]@users.noreply.github.com', 'name': 'whitesource-bolt-for-github[bot]'}, 'message': 'Add .whitesource configuration file', 'distinct': True, 'url': 'https://api.github.com/repos/LaudateCorpus1/haul/commits/f1ec06f177d707ae8191f423a3da9bd8b9e8854e'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546728', 'type': 'PushEvent', 'actor': {'id': 57829583, 'login': 'etkmlm', 'display_login': 'etkmlm', 'gravatar_id': '', 'url': 'https://api.github.com/users/etkmlm', 'avatar_url': 'https://avatars.githubusercontent.com/u/57829583?'}, 'repo': {'id': 427765240, 'name': 'etkmlm/CynthMusic', 'url': 'https://api.github.com/repos/etkmlm/CynthMusic'}, 'payload': {'push_id': 8993439206, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/master', 'head': '99b7992544765639d3c1e7402a663ef6cae4a9e9', 'before': 'c54014d51d75b33144701baeb12194d7a0694761', 'commits': [{'sha': '99b7992544765639d3c1e7402a663ef6cae4a9e9', 'author': {'email': 'furkanmahmutyilmaz@gmail.com', 'name': 'etkmlm'}, 'message': 'update', 'distinct': True, 'url': 'https://api.github.com/repos/etkmlm/CynthMusic/commits/99b7992544765639d3c1e7402a663ef6cae4a9e9'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546712', 'type': 'ForkEvent', 'actor': {'id': 71681815, 'login': 'LaudateCorpus1', 'display_login': 'LaudateCorpus1', 'gravatar_id': '', 'url': 'https://api.github.com/users/LaudateCorpus1', 'avatar_url': 'https://avatars.githubusercontent.com/u/71681815?'}, 'repo': {'id': 198903446, 'name': 'discord/react-async-component', 'url': 'https://api.github.com/repos/discord/react-async-component'}, 'payload': {'forkee': {'id': 454805316, 'node_id': 'R_kgDOGxvHRA', 'name': 'react-async-component', 'full_name': 'LaudateCorpus1/react-async-component', 'private': False, 'owner': {'login': 'LaudateCorpus1', 'id': 71681815, 'node_id': 'MDQ6VXNlcjcxNjgxODE1', 'avatar_url': 'https://avatars.githubusercontent.com/u/71681815?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/LaudateCorpus1', 'html_url': 'https://github.com/LaudateCorpus1', 'followers_url': 'https://api.github.com/users/LaudateCorpus1/followers', 'following_url': 'https://api.github.com/users/LaudateCorpus1/following{/other_user}', 'gists_url': 'https://api.github.com/users/LaudateCorpus1/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/LaudateCorpus1/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/LaudateCorpus1/subscriptions', 'organizations_url': 'https://api.github.com/users/LaudateCorpus1/orgs', 'repos_url': 'https://api.github.com/users/LaudateCorpus1/repos', 'events_url': 'https://api.github.com/users/LaudateCorpus1/events{/privacy}', 'received_events_url': 'https://api.github.com/users/LaudateCorpus1/received_events', 'type': 'User', 'site_admin': False}, 'html_url': 'https://github.com/LaudateCorpus1/react-async-component', 'description': 'Resolve components asynchronously, with support for code splitting and advanced server side rendering use cases.', 'fork': True, 'url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component', 'forks_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/forks', 'keys_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/teams', 'hooks_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/hooks', 'issue_events_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/issues/events{/number}', 'events_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/events', 'assignees_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/assignees{/user}', 'branches_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/branches{/branch}', 'tags_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/tags', 'blobs_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/languages', 'stargazers_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/stargazers', 'contributors_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/contributors', 'subscribers_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/subscribers', 'subscription_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/subscription', 'commits_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/contents/{+path}', 'compare_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/merges', 'archive_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/downloads', 'issues_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/issues{/number}', 'pulls_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/labels{/name}', 'releases_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/releases{/id}', 'deployments_url': 'https://api.github.com/repos/LaudateCorpus1/react-async-component/deployments', 'created_at': '2022-02-02T14:23:27Z', 'updated_at': '2021-04-28T21:28:49Z', 'pushed_at': '2019-07-25T21:34:03Z', 'git_url': 'git://github.com/LaudateCorpus1/react-async-component.git', 'ssh_url': 'git@github.com:LaudateCorpus1/react-async-component.git', 'clone_url': 'https://github.com/LaudateCorpus1/react-async-component.git', 'svn_url': 'https://github.com/LaudateCorpus1/react-async-component', 'homepage': '', 'size': 450, 'stargazers_count': 0, 'watchers_count': 0, 'language': None, 'has_issues': False, 'has_projects': True, 'has_downloads': True, 'has_wiki': True, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 0, 'license': {'key': 'mit', 'name': 'MIT License', 'spdx_id': 'MIT', 'url': 'https://api.github.com/licenses/mit', 'node_id': 'MDc6TGljZW5zZTEz'}, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 0, 'watchers': 0, 'default_branch': 'master', 'public': True}}, 'public': True, 'created_at': '2022-02-02T14:23:31Z', 'org': {'id': 1965106, 'login': 'discord', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/discord', 'avatar_url': 'https://avatars.githubusercontent.com/u/1965106?'}}, {'id': '20038546667', 'type': 'PushEvent', 'actor': {'id': 11934090, 'login': 'NickleDave', 'display_login': 'NickleDave', 'gravatar_id': '', 'url': 'https://api.github.com/users/NickleDave', 'avatar_url': 'https://avatars.githubusercontent.com/u/11934090?'}, 'repo': {'id': 369936952, 'name': 'NickleDave/vocalpy', 'url': 'https://api.github.com/repos/NickleDave/vocalpy'}, 'payload': {'push_id': 8993439062, 'size': 7, 'distinct_size': 7, 'ref': 'refs/heads/dev-0.1.0', 'head': '207fdb21d2d355a7d60d806d790f74764a92f784', 'before': '2fa1b3e2506c94c966cc35324344cc5099995364', 'commits': [{'sha': 'db2a2fc71e4eff8f1d3d6ecbee8a4224006dada8', 'author': {'email': 'nickledave@users.noreply.github.com', 'name': 'David Nicholson'}, 'message': 'revise src/vocalpy/dataclasses/audio.py', 'distinct': True, 'url': 'https://api.github.com/repos/NickleDave/vocalpy/commits/db2a2fc71e4eff8f1d3d6ecbee8a4224006dada8'}, {'sha': 'd9384b38a10ae8a58d67a6276837bd07892db5be', 'author': {'email': 'nickledave@users.noreply.github.com', 'name': 'David Nicholson'}, 'message': 'add tests/test_audio.py', 'distinct': True, 'url': 'https://api.github.com/repos/NickleDave/vocalpy/commits/d9384b38a10ae8a58d67a6276837bd07892db5be'}, {'sha': '07a848d271b677c1e203b1bf674d5426a28d6a2a', 'author': {'email': 'nickledave@users.noreply.github.com', 'name': 'David Nicholson'}, 'message': 'add .pre-commit-config.yaml', 'distinct': True, 'url': 'https://api.github.com/repos/NickleDave/vocalpy/commits/07a848d271b677c1e203b1bf674d5426a28d6a2a'}, {'sha': '7d52655873b7e40db728bf60d4e5916f03d9164f', 'author': {'email': 'nickledave@users.noreply.github.com', 'name': 'David Nicholson'}, 'message': 'add noxfile.py', 'distinct': True, 'url': 'https://api.github.com/repos/NickleDave/vocalpy/commits/7d52655873b7e40db728bf60d4e5916f03d9164f'}, {'sha': 'aaaf7b0f7ce448575443b0587a47ea8af3db5548', 'author': {'email': 'nickledave@users.noreply.github.com', 'name': 'David Nicholson'}, 'message': 'rewrite spectrogram to lazy load', 'distinct': True, 'url': 'https://api.github.com/repos/NickleDave/vocalpy/commits/aaaf7b0f7ce448575443b0587a47ea8af3db5548'}, {'sha': 'c4d880e3fa2bac229080b935e0e042f19a6ad7d3', 'author': {'email': 'nickledave@users.noreply.github.com', 'name': 'David Nicholson'}, 'message': 'move test_audio into tests/test_dataclasses/', 'distinct': True, 'url': 'https://api.github.com/repos/NickleDave/vocalpy/commits/c4d880e3fa2bac229080b935e0e042f19a6ad7d3'}, {'sha': '207fdb21d2d355a7d60d806d790f74764a92f784', 'author': {'email': 'nickledave@users.noreply.github.com', 'name': 'David Nicholson'}, 'message': 'WIP: add tests/test_dataclasses/test_spectrogram.py', 'distinct': True, 'url': 'https://api.github.com/repos/NickleDave/vocalpy/commits/207fdb21d2d355a7d60d806d790f74764a92f784'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546666', 'type': 'PushEvent', 'actor': {'id': 43951, 'login': 'joschi', 'display_login': 'joschi', 'gravatar_id': '', 'url': 'https://api.github.com/users/joschi', 'avatar_url': 'https://avatars.githubusercontent.com/u/43951?'}, 'repo': {'id': 315058783, 'name': 'joschi/asdf-vm-twitter', 'url': 'https://api.github.com/repos/joschi/asdf-vm-twitter'}, 'payload': {'push_id': 8993439101, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/main', 'head': 'ee6e8893fd37096190d74539303ca25688c642db', 'before': 'accb3220620ca0199f21d016fc4bc87b23ba6819', 'commits': [{'sha': 'ee6e8893fd37096190d74539303ca25688c642db', 'author': {'email': 'joschi@users.noreply.github.com', 'name': 'joschi'}, 'message': '🤖 Add new tweets 🐦', 'distinct': True, 'url': 'https://api.github.com/repos/joschi/asdf-vm-twitter/commits/ee6e8893fd37096190d74539303ca25688c642db'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546663', 'type': 'PullRequestReviewEvent', 'actor': {'id': 37936606, 'login': 'github-learning-lab[bot]', 'display_login': 'github-learning-lab', 'gravatar_id': '', 'url': 'https://api.github.com/users/github-learning-lab[bot]', 'avatar_url': 'https://avatars.githubusercontent.com/u/37936606?'}, 'repo': {'id': 448401719, 'name': 'programmer-georgia/github-actions-for-ci', 'url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci'}, 'payload': {'action': 'created', 'review': {'id': 870611919, 'node_id': 'PRR_kwDOGroRN84z5HvP', 'user': {'login': 'github-learning-lab[bot]', 'id': 37936606, 'node_id': 'MDM6Qm90Mzc5MzY2MDY=', 'avatar_url': 'https://avatars.githubusercontent.com/in/10572?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D', 'html_url': 'https://github.com/apps/github-learning-lab', 'followers_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/followers', 'following_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/following{/other_user}', 'gists_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/subscriptions', 'organizations_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/orgs', 'repos_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/repos', 'events_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/events{/privacy}', 'received_events_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/received_events', 'type': 'Bot', 'site_admin': False}, 'body': None, 'commit_id': '3d8bdc3c3b1bd57f2295509b26c532c2dc26871d', 'submitted_at': '2022-02-02T14:23:29Z', 'state': 'commented', 'html_url': 'https://github.com/programmer-georgia/github-actions-for-ci/pull/6#pullrequestreview-870611919', 'pull_request_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6', 'author_association': 'CONTRIBUTOR', '_links': {'html': {'href': 'https://github.com/programmer-georgia/github-actions-for-ci/pull/6#pullrequestreview-870611919'}, 'pull_request': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6'}}}, 'pull_request': {'url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6', 'id': 838342401, 'node_id': 'PR_kwDOGroRN84x-BcB', 'html_url': 'https://github.com/programmer-georgia/github-actions-for-ci/pull/6', 'diff_url': 'https://github.com/programmer-georgia/github-actions-for-ci/pull/6.diff', 'patch_url': 'https://github.com/programmer-georgia/github-actions-for-ci/pull/6.patch', 'issue_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/6', 'number': 6, 'state': 'open', 'locked': False, 'title': 'A custom workflow', 'user': {'login': 'github-learning-lab[bot]', 'id': 37936606, 'node_id': 'MDM6Qm90Mzc5MzY2MDY=', 'avatar_url': 'https://avatars.githubusercontent.com/in/10572?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D', 'html_url': 'https://github.com/apps/github-learning-lab', 'followers_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/followers', 'following_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/following{/other_user}', 'gists_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/subscriptions', 'organizations_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/orgs', 'repos_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/repos', 'events_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/events{/privacy}', 'received_events_url': 'https://api.github.com/users/github-learning-lab%5Bbot%5D/received_events', 'type': 'Bot', 'site_admin': False}, 'body': "# Partial workflow\n\nRemember the [custom workflow](https://github.com/programmer-georgia/github-actions-for-ci/issues/4) we are attempting to create for the team? Here's our status on the list of requirements we defined:\n\n- :white_check_mark: **test against multiple targets** so that we know if our supported operating systems and Node.js versions are working\n- :white_check_mark: **dedicated test job** so that we can separate out build from test details\n- :white_check_mark: **access to build artifacts** so that we can deploy them to a target environment\n- **branch protections** so that the `main` branch can't be deleted or inadvertently broken\n- **required reviews** so that any pull requests are double checked by teammates\n- **obvious approvals** so we can merge quickly and potentially automate merges and deployments\n\nThe last three remaining items don't really belong in a `code, build, and test` pipeline because they have to do with processes that involve humans.\n\n## Step 14: Automate the review process\n\nGitHub Actions can run multiple workflows for different event triggers. Let's create a new approval workflow that'll work together with our Node.js workflow.\n\n### :keyboard: Activity: Add a new workflow file to automate the team's review process\n\n1. Create a [new file](https://github.com/programmer-georgia/github-actions-for-ci/new/team-workflow/?filename=.github/workflows/approval-workflow.yml), `.github/workflows/approval-workflow.yml`, on this branch\n1. Enter a name for your workflow in the new file, something like:\n ```yaml\n name: Team awesome's approval workflow\n ```\n\nI'll respond when you commit to this branch.\n", 'created_at': '2022-02-02T14:07:12Z', 'updated_at': '2022-02-02T14:23:29Z', 'closed_at': None, 'merged_at': None, 'merge_commit_sha': '89a43d463fd28691902ccb165e09e7385b63b0bd', 'assignee': None, 'assignees': [], 'requested_reviewers': [], 'requested_teams': [], 'labels': [], 'milestone': None, 'draft': False, 'commits_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6/commits', 'review_comments_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6/comments', 'review_comment_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/comments{/number}', 'comments_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/6/comments', 'statuses_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/statuses/3d8bdc3c3b1bd57f2295509b26c532c2dc26871d', 'head': {'label': 'programmer-georgia:team-workflow', 'ref': 'team-workflow', 'sha': '3d8bdc3c3b1bd57f2295509b26c532c2dc26871d', 'user': {'login': 'programmer-georgia', 'id': 96337743, 'node_id': 'U_kgDOBb3_Tw', 'avatar_url': 'https://avatars.githubusercontent.com/u/96337743?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/programmer-georgia', 'html_url': 'https://github.com/programmer-georgia', 'followers_url': 'https://api.github.com/users/programmer-georgia/followers', 'following_url': 'https://api.github.com/users/programmer-georgia/following{/other_user}', 'gists_url': 'https://api.github.com/users/programmer-georgia/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/programmer-georgia/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/programmer-georgia/subscriptions', 'organizations_url': 'https://api.github.com/users/programmer-georgia/orgs', 'repos_url': 'https://api.github.com/users/programmer-georgia/repos', 'events_url': 'https://api.github.com/users/programmer-georgia/events{/privacy}', 'received_events_url': 'https://api.github.com/users/programmer-georgia/received_events', 'type': 'User', 'site_admin': False}, 'repo': {'id': 448401719, 'node_id': 'R_kgDOGroRNw', 'name': 'github-actions-for-ci', 'full_name': 'programmer-georgia/github-actions-for-ci', 'private': False, 'owner': {'login': 'programmer-georgia', 'id': 96337743, 'node_id': 'U_kgDOBb3_Tw', 'avatar_url': 'https://avatars.githubusercontent.com/u/96337743?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/programmer-georgia', 'html_url': 'https://github.com/programmer-georgia', 'followers_url': 'https://api.github.com/users/programmer-georgia/followers', 'following_url': 'https://api.github.com/users/programmer-georgia/following{/other_user}', 'gists_url': 'https://api.github.com/users/programmer-georgia/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/programmer-georgia/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/programmer-georgia/subscriptions', 'organizations_url': 'https://api.github.com/users/programmer-georgia/orgs', 'repos_url': 'https://api.github.com/users/programmer-georgia/repos', 'events_url': 'https://api.github.com/users/programmer-georgia/events{/privacy}', 'received_events_url': 'https://api.github.com/users/programmer-georgia/received_events', 'type': 'User', 'site_admin': False}, 'html_url': 'https://github.com/programmer-georgia/github-actions-for-ci', 'description': None, 'fork': False, 'url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci', 'forks_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/forks', 'keys_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/teams', 'hooks_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/hooks', 'issue_events_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/events{/number}', 'events_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/events', 'assignees_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/assignees{/user}', 'branches_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/branches{/branch}', 'tags_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/tags', 'blobs_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/languages', 'stargazers_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/stargazers', 'contributors_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/contributors', 'subscribers_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/subscribers', 'subscription_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/subscription', 'commits_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/contents/{+path}', 'compare_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/merges', 'archive_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/downloads', 'issues_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues{/number}', 'pulls_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/labels{/name}', 'releases_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/releases{/id}', 'deployments_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/deployments', 'created_at': '2022-01-15T22:07:43Z', 'updated_at': '2022-01-15T22:07:48Z', 'pushed_at': '2022-02-02T14:23:28Z', 'git_url': 'git://github.com/programmer-georgia/github-actions-for-ci.git', 'ssh_url': 'git@github.com:programmer-georgia/github-actions-for-ci.git', 'clone_url': 'https://github.com/programmer-georgia/github-actions-for-ci.git', 'svn_url': 'https://github.com/programmer-georgia/github-actions-for-ci', 'homepage': 'https://lab.github.com/githubtraining/github-actions:-continuous-integration', 'size': 282, 'stargazers_count': 0, 'watchers_count': 0, 'language': 'JavaScript', 'has_issues': True, 'has_projects': True, 'has_downloads': True, 'has_wiki': True, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 3, 'license': {'key': 'mit', 'name': 'MIT License', 'spdx_id': 'MIT', 'url': 'https://api.github.com/licenses/mit', 'node_id': 'MDc6TGljZW5zZTEz'}, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 3, 'watchers': 0, 'default_branch': 'main'}}, 'base': {'label': 'programmer-georgia:main', 'ref': 'main', 'sha': '71232a170144f5d03c18f6ad1fad546a38072274', 'user': {'login': 'programmer-georgia', 'id': 96337743, 'node_id': 'U_kgDOBb3_Tw', 'avatar_url': 'https://avatars.githubusercontent.com/u/96337743?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/programmer-georgia', 'html_url': 'https://github.com/programmer-georgia', 'followers_url': 'https://api.github.com/users/programmer-georgia/followers', 'following_url': 'https://api.github.com/users/programmer-georgia/following{/other_user}', 'gists_url': 'https://api.github.com/users/programmer-georgia/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/programmer-georgia/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/programmer-georgia/subscriptions', 'organizations_url': 'https://api.github.com/users/programmer-georgia/orgs', 'repos_url': 'https://api.github.com/users/programmer-georgia/repos', 'events_url': 'https://api.github.com/users/programmer-georgia/events{/privacy}', 'received_events_url': 'https://api.github.com/users/programmer-georgia/received_events', 'type': 'User', 'site_admin': False}, 'repo': {'id': 448401719, 'node_id': 'R_kgDOGroRNw', 'name': 'github-actions-for-ci', 'full_name': 'programmer-georgia/github-actions-for-ci', 'private': False, 'owner': {'login': 'programmer-georgia', 'id': 96337743, 'node_id': 'U_kgDOBb3_Tw', 'avatar_url': 'https://avatars.githubusercontent.com/u/96337743?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/programmer-georgia', 'html_url': 'https://github.com/programmer-georgia', 'followers_url': 'https://api.github.com/users/programmer-georgia/followers', 'following_url': 'https://api.github.com/users/programmer-georgia/following{/other_user}', 'gists_url': 'https://api.github.com/users/programmer-georgia/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/programmer-georgia/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/programmer-georgia/subscriptions', 'organizations_url': 'https://api.github.com/users/programmer-georgia/orgs', 'repos_url': 'https://api.github.com/users/programmer-georgia/repos', 'events_url': 'https://api.github.com/users/programmer-georgia/events{/privacy}', 'received_events_url': 'https://api.github.com/users/programmer-georgia/received_events', 'type': 'User', 'site_admin': False}, 'html_url': 'https://github.com/programmer-georgia/github-actions-for-ci', 'description': None, 'fork': False, 'url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci', 'forks_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/forks', 'keys_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/teams', 'hooks_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/hooks', 'issue_events_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/events{/number}', 'events_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/events', 'assignees_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/assignees{/user}', 'branches_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/branches{/branch}', 'tags_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/tags', 'blobs_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/languages', 'stargazers_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/stargazers', 'contributors_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/contributors', 'subscribers_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/subscribers', 'subscription_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/subscription', 'commits_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/contents/{+path}', 'compare_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/merges', 'archive_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/downloads', 'issues_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues{/number}', 'pulls_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/labels{/name}', 'releases_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/releases{/id}', 'deployments_url': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/deployments', 'created_at': '2022-01-15T22:07:43Z', 'updated_at': '2022-01-15T22:07:48Z', 'pushed_at': '2022-02-02T14:23:28Z', 'git_url': 'git://github.com/programmer-georgia/github-actions-for-ci.git', 'ssh_url': 'git@github.com:programmer-georgia/github-actions-for-ci.git', 'clone_url': 'https://github.com/programmer-georgia/github-actions-for-ci.git', 'svn_url': 'https://github.com/programmer-georgia/github-actions-for-ci', 'homepage': 'https://lab.github.com/githubtraining/github-actions:-continuous-integration', 'size': 282, 'stargazers_count': 0, 'watchers_count': 0, 'language': 'JavaScript', 'has_issues': True, 'has_projects': True, 'has_downloads': True, 'has_wiki': True, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 3, 'license': {'key': 'mit', 'name': 'MIT License', 'spdx_id': 'MIT', 'url': 'https://api.github.com/licenses/mit', 'node_id': 'MDc6TGljZW5zZTEz'}, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 3, 'watchers': 0, 'default_branch': 'main'}}, '_links': {'self': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6'}, 'html': {'href': 'https://github.com/programmer-georgia/github-actions-for-ci/pull/6'}, 'issue': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/6'}, 'comments': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/issues/6/comments'}, 'review_comments': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6/comments'}, 'review_comment': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/comments{/number}'}, 'commits': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/pulls/6/commits'}, 'statuses': {'href': 'https://api.github.com/repos/programmer-georgia/github-actions-for-ci/statuses/3d8bdc3c3b1bd57f2295509b26c532c2dc26871d'}}, 'author_association': 'CONTRIBUTOR', 'auto_merge': None, 'active_lock_reason': None}}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546662', 'type': 'PullRequestEvent', 'actor': {'id': 7466850, 'login': 'Wricken', 'display_login': 'Wricken', 'gravatar_id': '', 'url': 'https://api.github.com/users/Wricken', 'avatar_url': 'https://avatars.githubusercontent.com/u/7466850?'}, 'repo': {'id': 352591585, 'name': 'Wricken/node-test', 'url': 'https://api.github.com/repos/Wricken/node-test'}, 'payload': {'action': 'closed', 'number': 15, 'pull_request': {'url': 'https://api.github.com/repos/Wricken/node-test/pulls/15', 'id': 838358100, 'node_id': 'PR_kwDOFQQe4c4x-FRU', 'html_url': 'https://github.com/Wricken/node-test/pull/15', 'diff_url': 'https://github.com/Wricken/node-test/pull/15.diff', 'patch_url': 'https://github.com/Wricken/node-test/pull/15.patch', 'issue_url': 'https://api.github.com/repos/Wricken/node-test/issues/15', 'number': 15, 'state': 'closed', 'locked': False, 'title': 'Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Update server.js"""""""""', 'user': {'login': 'Wricken', 'id': 7466850, 'node_id': 'MDQ6VXNlcjc0NjY4NTA=', 'avatar_url': 'https://avatars.githubusercontent.com/u/7466850?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/Wricken', 'html_url': 'https://github.com/Wricken', 'followers_url': 'https://api.github.com/users/Wricken/followers', 'following_url': 'https://api.github.com/users/Wricken/following{/other_user}', 'gists_url': 'https://api.github.com/users/Wricken/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/Wricken/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/Wricken/subscriptions', 'organizations_url': 'https://api.github.com/users/Wricken/orgs', 'repos_url': 'https://api.github.com/users/Wricken/repos', 'events_url': 'https://api.github.com/users/Wricken/events{/privacy}', 'received_events_url': 'https://api.github.com/users/Wricken/received_events', 'type': 'User', 'site_admin': False}, 'body': 'Reverts Wricken/node-test#14', 'created_at': '2022-02-02T14:23:14Z', 'updated_at': '2022-02-02T14:23:29Z', 'closed_at': '2022-02-02T14:23:29Z', 'merged_at': '2022-02-02T14:23:29Z', 'merge_commit_sha': '8011082e196461862c7690f351bdf5d3e8f01125', 'assignee': None, 'assignees': [], 'requested_reviewers': [], 'requested_teams': [], 'labels': [], 'milestone': None, 'draft': False, 'commits_url': 'https://api.github.com/repos/Wricken/node-test/pulls/15/commits', 'review_comments_url': 'https://api.github.com/repos/Wricken/node-test/pulls/15/comments', 'review_comment_url': 'https://api.github.com/repos/Wricken/node-test/pulls/comments{/number}', 'comments_url': 'https://api.github.com/repos/Wricken/node-test/issues/15/comments', 'statuses_url': 'https://api.github.com/repos/Wricken/node-test/statuses/6e20855d432dcabed8e2653d774152f55dc915c3', 'head': {'label': 'Wricken:revert-14-revert-13-revert-12-revert-11-revert-10-revert-9-revert-8-revert-7-revert-6-Wricken-patewffewfewfewch-1', 'ref': 'revert-14-revert-13-revert-12-revert-11-revert-10-revert-9-revert-8-revert-7-revert-6-Wricken-patewffewfewfewch-1', 'sha': '6e20855d432dcabed8e2653d774152f55dc915c3', 'user': {'login': 'Wricken', 'id': 7466850, 'node_id': 'MDQ6VXNlcjc0NjY4NTA=', 'avatar_url': 'https://avatars.githubusercontent.com/u/7466850?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/Wricken', 'html_url': 'https://github.com/Wricken', 'followers_url': 'https://api.github.com/users/Wricken/followers', 'following_url': 'https://api.github.com/users/Wricken/following{/other_user}', 'gists_url': 'https://api.github.com/users/Wricken/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/Wricken/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/Wricken/subscriptions', 'organizations_url': 'https://api.github.com/users/Wricken/orgs', 'repos_url': 'https://api.github.com/users/Wricken/repos', 'events_url': 'https://api.github.com/users/Wricken/events{/privacy}', 'received_events_url': 'https://api.github.com/users/Wricken/received_events', 'type': 'User', 'site_admin': False}, 'repo': {'id': 352591585, 'node_id': 'MDEwOlJlcG9zaXRvcnkzNTI1OTE1ODU=', 'name': 'node-test', 'full_name': 'Wricken/node-test', 'private': False, 'owner': {'login': 'Wricken', 'id': 7466850, 'node_id': 'MDQ6VXNlcjc0NjY4NTA=', 'avatar_url': 'https://avatars.githubusercontent.com/u/7466850?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/Wricken', 'html_url': 'https://github.com/Wricken', 'followers_url': 'https://api.github.com/users/Wricken/followers', 'following_url': 'https://api.github.com/users/Wricken/following{/other_user}', 'gists_url': 'https://api.github.com/users/Wricken/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/Wricken/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/Wricken/subscriptions', 'organizations_url': 'https://api.github.com/users/Wricken/orgs', 'repos_url': 'https://api.github.com/users/Wricken/repos', 'events_url': 'https://api.github.com/users/Wricken/events{/privacy}', 'received_events_url': 'https://api.github.com/users/Wricken/received_events', 'type': 'User', 'site_admin': False}, 'html_url': 'https://github.com/Wricken/node-test', 'description': None, 'fork': False, 'url': 'https://api.github.com/repos/Wricken/node-test', 'forks_url': 'https://api.github.com/repos/Wricken/node-test/forks', 'keys_url': 'https://api.github.com/repos/Wricken/node-test/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/Wricken/node-test/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/Wricken/node-test/teams', 'hooks_url': 'https://api.github.com/repos/Wricken/node-test/hooks', 'issue_events_url': 'https://api.github.com/repos/Wricken/node-test/issues/events{/number}', 'events_url': 'https://api.github.com/repos/Wricken/node-test/events', 'assignees_url': 'https://api.github.com/repos/Wricken/node-test/assignees{/user}', 'branches_url': 'https://api.github.com/repos/Wricken/node-test/branches{/branch}', 'tags_url': 'https://api.github.com/repos/Wricken/node-test/tags', 'blobs_url': 'https://api.github.com/repos/Wricken/node-test/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/Wricken/node-test/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/Wricken/node-test/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/Wricken/node-test/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/Wricken/node-test/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/Wricken/node-test/languages', 'stargazers_url': 'https://api.github.com/repos/Wricken/node-test/stargazers', 'contributors_url': 'https://api.github.com/repos/Wricken/node-test/contributors', 'subscribers_url': 'https://api.github.com/repos/Wricken/node-test/subscribers', 'subscription_url': 'https://api.github.com/repos/Wricken/node-test/subscription', 'commits_url': 'https://api.github.com/repos/Wricken/node-test/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/Wricken/node-test/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/Wricken/node-test/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/Wricken/node-test/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/Wricken/node-test/contents/{+path}', 'compare_url': 'https://api.github.com/repos/Wricken/node-test/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/Wricken/node-test/merges', 'archive_url': 'https://api.github.com/repos/Wricken/node-test/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/Wricken/node-test/downloads', 'issues_url': 'https://api.github.com/repos/Wricken/node-test/issues{/number}', 'pulls_url': 'https://api.github.com/repos/Wricken/node-test/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/Wricken/node-test/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/Wricken/node-test/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/Wricken/node-test/labels{/name}', 'releases_url': 'https://api.github.com/repos/Wricken/node-test/releases{/id}', 'deployments_url': 'https://api.github.com/repos/Wricken/node-test/deployments', 'created_at': '2021-03-29T09:44:50Z', 'updated_at': '2022-02-02T06:59:20Z', 'pushed_at': '2022-02-02T14:23:29Z', 'git_url': 'git://github.com/Wricken/node-test.git', 'ssh_url': 'git@github.com:Wricken/node-test.git', 'clone_url': 'https://github.com/Wricken/node-test.git', 'svn_url': 'https://github.com/Wricken/node-test', 'homepage': None, 'size': 706, 'stargazers_count': 0, 'watchers_count': 0, 'language': 'JavaScript', 'has_issues': False, 'has_projects': False, 'has_downloads': True, 'has_wiki': False, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 0, 'license': None, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 0, 'watchers': 0, 'default_branch': 'main'}}, 'base': {'label': 'Wricken:main', 'ref': 'main', 'sha': '6f72705905fdb65eb4f82fac14703ff199a69b7c', 'user': {'login': 'Wricken', 'id': 7466850, 'node_id': 'MDQ6VXNlcjc0NjY4NTA=', 'avatar_url': 'https://avatars.githubusercontent.com/u/7466850?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/Wricken', 'html_url': 'https://github.com/Wricken', 'followers_url': 'https://api.github.com/users/Wricken/followers', 'following_url': 'https://api.github.com/users/Wricken/following{/other_user}', 'gists_url': 'https://api.github.com/users/Wricken/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/Wricken/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/Wricken/subscriptions', 'organizations_url': 'https://api.github.com/users/Wricken/orgs', 'repos_url': 'https://api.github.com/users/Wricken/repos', 'events_url': 'https://api.github.com/users/Wricken/events{/privacy}', 'received_events_url': 'https://api.github.com/users/Wricken/received_events', 'type': 'User', 'site_admin': False}, 'repo': {'id': 352591585, 'node_id': 'MDEwOlJlcG9zaXRvcnkzNTI1OTE1ODU=', 'name': 'node-test', 'full_name': 'Wricken/node-test', 'private': False, 'owner': {'login': 'Wricken', 'id': 7466850, 'node_id': 'MDQ6VXNlcjc0NjY4NTA=', 'avatar_url': 'https://avatars.githubusercontent.com/u/7466850?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/Wricken', 'html_url': 'https://github.com/Wricken', 'followers_url': 'https://api.github.com/users/Wricken/followers', 'following_url': 'https://api.github.com/users/Wricken/following{/other_user}', 'gists_url': 'https://api.github.com/users/Wricken/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/Wricken/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/Wricken/subscriptions', 'organizations_url': 'https://api.github.com/users/Wricken/orgs', 'repos_url': 'https://api.github.com/users/Wricken/repos', 'events_url': 'https://api.github.com/users/Wricken/events{/privacy}', 'received_events_url': 'https://api.github.com/users/Wricken/received_events', 'type': 'User', 'site_admin': False}, 'html_url': 'https://github.com/Wricken/node-test', 'description': None, 'fork': False, 'url': 'https://api.github.com/repos/Wricken/node-test', 'forks_url': 'https://api.github.com/repos/Wricken/node-test/forks', 'keys_url': 'https://api.github.com/repos/Wricken/node-test/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/Wricken/node-test/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/Wricken/node-test/teams', 'hooks_url': 'https://api.github.com/repos/Wricken/node-test/hooks', 'issue_events_url': 'https://api.github.com/repos/Wricken/node-test/issues/events{/number}', 'events_url': 'https://api.github.com/repos/Wricken/node-test/events', 'assignees_url': 'https://api.github.com/repos/Wricken/node-test/assignees{/user}', 'branches_url': 'https://api.github.com/repos/Wricken/node-test/branches{/branch}', 'tags_url': 'https://api.github.com/repos/Wricken/node-test/tags', 'blobs_url': 'https://api.github.com/repos/Wricken/node-test/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/Wricken/node-test/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/Wricken/node-test/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/Wricken/node-test/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/Wricken/node-test/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/Wricken/node-test/languages', 'stargazers_url': 'https://api.github.com/repos/Wricken/node-test/stargazers', 'contributors_url': 'https://api.github.com/repos/Wricken/node-test/contributors', 'subscribers_url': 'https://api.github.com/repos/Wricken/node-test/subscribers', 'subscription_url': 'https://api.github.com/repos/Wricken/node-test/subscription', 'commits_url': 'https://api.github.com/repos/Wricken/node-test/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/Wricken/node-test/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/Wricken/node-test/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/Wricken/node-test/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/Wricken/node-test/contents/{+path}', 'compare_url': 'https://api.github.com/repos/Wricken/node-test/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/Wricken/node-test/merges', 'archive_url': 'https://api.github.com/repos/Wricken/node-test/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/Wricken/node-test/downloads', 'issues_url': 'https://api.github.com/repos/Wricken/node-test/issues{/number}', 'pulls_url': 'https://api.github.com/repos/Wricken/node-test/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/Wricken/node-test/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/Wricken/node-test/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/Wricken/node-test/labels{/name}', 'releases_url': 'https://api.github.com/repos/Wricken/node-test/releases{/id}', 'deployments_url': 'https://api.github.com/repos/Wricken/node-test/deployments', 'created_at': '2021-03-29T09:44:50Z', 'updated_at': '2022-02-02T06:59:20Z', 'pushed_at': '2022-02-02T14:23:29Z', 'git_url': 'git://github.com/Wricken/node-test.git', 'ssh_url': 'git@github.com:Wricken/node-test.git', 'clone_url': 'https://github.com/Wricken/node-test.git', 'svn_url': 'https://github.com/Wricken/node-test', 'homepage': None, 'size': 706, 'stargazers_count': 0, 'watchers_count': 0, 'language': 'JavaScript', 'has_issues': False, 'has_projects': False, 'has_downloads': True, 'has_wiki': False, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 0, 'license': None, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 0, 'watchers': 0, 'default_branch': 'main'}}, '_links': {'self': {'href': 'https://api.github.com/repos/Wricken/node-test/pulls/15'}, 'html': {'href': 'https://github.com/Wricken/node-test/pull/15'}, 'issue': {'href': 'https://api.github.com/repos/Wricken/node-test/issues/15'}, 'comments': {'href': 'https://api.github.com/repos/Wricken/node-test/issues/15/comments'}, 'review_comments': {'href': 'https://api.github.com/repos/Wricken/node-test/pulls/15/comments'}, 'review_comment': {'href': 'https://api.github.com/repos/Wricken/node-test/pulls/comments{/number}'}, 'commits': {'href': 'https://api.github.com/repos/Wricken/node-test/pulls/15/commits'}, 'statuses': {'href': 'https://api.github.com/repos/Wricken/node-test/statuses/6e20855d432dcabed8e2653d774152f55dc915c3'}}, 'author_association': 'OWNER', 'auto_merge': None, 'active_lock_reason': None, 'merged': True, 'mergeable': None, 'rebaseable': None, 'mergeable_state': 'unknown', 'merged_by': {'login': 'Wricken', 'id': 7466850, 'node_id': 'MDQ6VXNlcjc0NjY4NTA=', 'avatar_url': 'https://avatars.githubusercontent.com/u/7466850?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/Wricken', 'html_url': 'https://github.com/Wricken', 'followers_url': 'https://api.github.com/users/Wricken/followers', 'following_url': 'https://api.github.com/users/Wricken/following{/other_user}', 'gists_url': 'https://api.github.com/users/Wricken/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/Wricken/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/Wricken/subscriptions', 'organizations_url': 'https://api.github.com/users/Wricken/orgs', 'repos_url': 'https://api.github.com/users/Wricken/repos', 'events_url': 'https://api.github.com/users/Wricken/events{/privacy}', 'received_events_url': 'https://api.github.com/users/Wricken/received_events', 'type': 'User', 'site_admin': False}, 'comments': 0, 'review_comments': 0, 'maintainer_can_modify': False, 'commits': 1, 'additions': 1, 'deletions': 1, 'changed_files': 1}}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546668', 'type': 'PushEvent', 'actor': {'id': 33487926, 'login': 'KornevNikita', 'display_login': 'KornevNikita', 'gravatar_id': '', 'url': 'https://api.github.com/users/KornevNikita', 'avatar_url': 'https://avatars.githubusercontent.com/u/33487926?'}, 'repo': {'id': 362404309, 'name': 'KornevNikita/SPIRV-LLVM-Translator', 'url': 'https://api.github.com/repos/KornevNikita/SPIRV-LLVM-Translator'}, 'payload': {'push_id': 8993439039, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/printf', 'head': 'ecdd28c7ae73a15e45b4fa74aefcfa5c948aad7a', 'before': '8e421f5ba2d5a3ffd932cc88badf8a2d7c57ecb0', 'commits': [{'sha': 'ecdd28c7ae73a15e45b4fa74aefcfa5c948aad7a', 'author': {'email': 'nikita.kornev@intel.com', 'name': 'Nikita Kornev'}, 'message': 'Fix out-of-tree warning', 'distinct': True, 'url': 'https://api.github.com/repos/KornevNikita/SPIRV-LLVM-Translator/commits/ecdd28c7ae73a15e45b4fa74aefcfa5c948aad7a'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546475', 'type': 'PushEvent', 'actor': {'id': 61689499, 'login': 'Chariselyasa123', 'display_login': 'Chariselyasa123', 'gravatar_id': '', 'url': 'https://api.github.com/users/Chariselyasa123', 'avatar_url': 'https://avatars.githubusercontent.com/u/61689499?'}, 'repo': {'id': 442054872, 'name': 'Chariselyasa123/penghjauan-github', 'url': 'https://api.github.com/repos/Chariselyasa123/penghjauan-github'}, 'payload': {'push_id': 8993438927, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/master', 'head': 'a6a642068eb8e4805b2ce7adb2eef6029ba2b850', 'before': 'ac5ad154ce58207e1980907258f6816d020dfbe3', 'commits': [{'sha': 'a6a642068eb8e4805b2ce7adb2eef6029ba2b850', 'author': {'email': 'ahmad.charis@raharja.info', 'name': 'Chariselyasa123'}, 'message': 'feat: plant a tree 🎋', 'distinct': True, 'url': 'https://api.github.com/repos/Chariselyasa123/penghjauan-github/commits/a6a642068eb8e4805b2ce7adb2eef6029ba2b850'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z'}, {'id': '20038546616', 'type': 'PullRequestReviewEvent', 'actor': {'id': 38854967, 'login': 'otc-zuul[bot]', 'display_login': 'otc-zuul', 'gravatar_id': '', 'url': 'https://api.github.com/users/otc-zuul[bot]', 'avatar_url': 'https://avatars.githubusercontent.com/u/38854967?'}, 'repo': {'id': 438200218, 'name': 'opentelekomcloud-infra/identity-deploy', 'url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy'}, 'payload': {'action': 'created', 'review': {'id': 870611929, 'node_id': 'PRR_kwDOGh5nms4z5HvZ', 'user': {'login': 'otc-zuul[bot]', 'id': 38854967, 'node_id': 'MDM6Qm90Mzg4NTQ5Njc=', 'avatar_url': 'https://avatars.githubusercontent.com/in/11628?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/otc-zuul%5Bbot%5D', 'html_url': 'https://github.com/apps/otc-zuul', 'followers_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/followers', 'following_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/following{/other_user}', 'gists_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/subscriptions', 'organizations_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/orgs', 'repos_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/repos', 'events_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/events{/privacy}', 'received_events_url': 'https://api.github.com/users/otc-zuul%5Bbot%5D/received_events', 'type': 'Bot', 'site_admin': False}, 'body': '', 'commit_id': '3673ec03da18e60a697368ef16d28c4b89e54228', 'submitted_at': '2022-02-02T14:23:30Z', 'state': 'approved', 'html_url': 'https://github.com/opentelekomcloud-infra/identity-deploy/pull/16#pullrequestreview-870611929', 'pull_request_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16', 'author_association': 'NONE', '_links': {'html': {'href': 'https://github.com/opentelekomcloud-infra/identity-deploy/pull/16#pullrequestreview-870611929'}, 'pull_request': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16'}}}, 'pull_request': {'url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16', 'id': 838338863, 'node_id': 'PR_kwDOGh5nms4x-Akv', 'html_url': 'https://github.com/opentelekomcloud-infra/identity-deploy/pull/16', 'diff_url': 'https://github.com/opentelekomcloud-infra/identity-deploy/pull/16.diff', 'patch_url': 'https://github.com/opentelekomcloud-infra/identity-deploy/pull/16.patch', 'issue_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/16', 'number': 16, 'state': 'open', 'locked': False, 'title': 'Add deeper zuul itegration', 'user': {'login': 'outcatcher', 'id': 8591561, 'node_id': 'MDQ6VXNlcjg1OTE1NjE=', 'avatar_url': 'https://avatars.githubusercontent.com/u/8591561?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/outcatcher', 'html_url': 'https://github.com/outcatcher', 'followers_url': 'https://api.github.com/users/outcatcher/followers', 'following_url': 'https://api.github.com/users/outcatcher/following{/other_user}', 'gists_url': 'https://api.github.com/users/outcatcher/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/outcatcher/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/outcatcher/subscriptions', 'organizations_url': 'https://api.github.com/users/outcatcher/orgs', 'repos_url': 'https://api.github.com/users/outcatcher/repos', 'events_url': 'https://api.github.com/users/outcatcher/events{/privacy}', 'received_events_url': 'https://api.github.com/users/outcatcher/received_events', 'type': 'User', 'site_admin': False}, 'body': 'Add two new zuul jobs:\r\n- `tox-functional-identity`\r\n- `golang-make-functional-identity`\r\n\r\nInheriting from `tox-functional` and `golang-make-functional` jobs respectively and deploying identity service on OTC VM.', 'created_at': '2022-02-02T14:03:28Z', 'updated_at': '2022-02-02T14:23:30Z', 'closed_at': None, 'merged_at': None, 'merge_commit_sha': 'd03fd4ec046c634c71ac82d2184e600825662cbe', 'assignee': None, 'assignees': [], 'requested_reviewers': [{'login': 'Polina-Gubina', 'id': 33940358, 'node_id': 'MDQ6VXNlcjMzOTQwMzU4', 'avatar_url': 'https://avatars.githubusercontent.com/u/33940358?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/Polina-Gubina', 'html_url': 'https://github.com/Polina-Gubina', 'followers_url': 'https://api.github.com/users/Polina-Gubina/followers', 'following_url': 'https://api.github.com/users/Polina-Gubina/following{/other_user}', 'gists_url': 'https://api.github.com/users/Polina-Gubina/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/Polina-Gubina/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/Polina-Gubina/subscriptions', 'organizations_url': 'https://api.github.com/users/Polina-Gubina/orgs', 'repos_url': 'https://api.github.com/users/Polina-Gubina/repos', 'events_url': 'https://api.github.com/users/Polina-Gubina/events{/privacy}', 'received_events_url': 'https://api.github.com/users/Polina-Gubina/received_events', 'type': 'User', 'site_admin': False}], 'requested_teams': [], 'labels': [{'id': 3640932468, 'node_id': 'LA_kwDOGh5nms7ZBDh0', 'url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/labels/post', 'name': 'post', 'color': 'FEF2C0', 'default': False, 'description': 'Execute check-post pipeline'}], 'milestone': None, 'draft': False, 'commits_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16/commits', 'review_comments_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16/comments', 'review_comment_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/comments{/number}', 'comments_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/16/comments', 'statuses_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/statuses/3673ec03da18e60a697368ef16d28c4b89e54228', 'head': {'label': 'opentelekomcloud-infra:zuul-identity', 'ref': 'zuul-identity', 'sha': '3673ec03da18e60a697368ef16d28c4b89e54228', 'user': {'login': 'opentelekomcloud-infra', 'id': 45656414, 'node_id': 'MDEyOk9yZ2FuaXphdGlvbjQ1NjU2NDE0', 'avatar_url': 'https://avatars.githubusercontent.com/u/45656414?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/opentelekomcloud-infra', 'html_url': 'https://github.com/opentelekomcloud-infra', 'followers_url': 'https://api.github.com/users/opentelekomcloud-infra/followers', 'following_url': 'https://api.github.com/users/opentelekomcloud-infra/following{/other_user}', 'gists_url': 'https://api.github.com/users/opentelekomcloud-infra/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/opentelekomcloud-infra/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/opentelekomcloud-infra/subscriptions', 'organizations_url': 'https://api.github.com/users/opentelekomcloud-infra/orgs', 'repos_url': 'https://api.github.com/users/opentelekomcloud-infra/repos', 'events_url': 'https://api.github.com/users/opentelekomcloud-infra/events{/privacy}', 'received_events_url': 'https://api.github.com/users/opentelekomcloud-infra/received_events', 'type': 'Organization', 'site_admin': False}, 'repo': {'id': 438200218, 'node_id': 'R_kgDOGh5nmg', 'name': 'identity-deploy', 'full_name': 'opentelekomcloud-infra/identity-deploy', 'private': False, 'owner': {'login': 'opentelekomcloud-infra', 'id': 45656414, 'node_id': 'MDEyOk9yZ2FuaXphdGlvbjQ1NjU2NDE0', 'avatar_url': 'https://avatars.githubusercontent.com/u/45656414?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/opentelekomcloud-infra', 'html_url': 'https://github.com/opentelekomcloud-infra', 'followers_url': 'https://api.github.com/users/opentelekomcloud-infra/followers', 'following_url': 'https://api.github.com/users/opentelekomcloud-infra/following{/other_user}', 'gists_url': 'https://api.github.com/users/opentelekomcloud-infra/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/opentelekomcloud-infra/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/opentelekomcloud-infra/subscriptions', 'organizations_url': 'https://api.github.com/users/opentelekomcloud-infra/orgs', 'repos_url': 'https://api.github.com/users/opentelekomcloud-infra/repos', 'events_url': 'https://api.github.com/users/opentelekomcloud-infra/events{/privacy}', 'received_events_url': 'https://api.github.com/users/opentelekomcloud-infra/received_events', 'type': 'Organization', 'site_admin': False}, 'html_url': 'https://github.com/opentelekomcloud-infra/identity-deploy', 'description': 'Ansible playbook to deploy stand-alone OpenStack keystone service', 'fork': True, 'url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy', 'forks_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/forks', 'keys_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/teams', 'hooks_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/hooks', 'issue_events_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/events{/number}', 'events_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/events', 'assignees_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/assignees{/user}', 'branches_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/branches{/branch}', 'tags_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/tags', 'blobs_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/languages', 'stargazers_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/stargazers', 'contributors_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/contributors', 'subscribers_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/subscribers', 'subscription_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/subscription', 'commits_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/contents/{+path}', 'compare_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/merges', 'archive_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/downloads', 'issues_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues{/number}', 'pulls_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/labels{/name}', 'releases_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/releases{/id}', 'deployments_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/deployments', 'created_at': '2021-12-14T09:55:15Z', 'updated_at': '2021-12-29T10:33:01Z', 'pushed_at': '2022-02-02T14:20:41Z', 'git_url': 'git://github.com/opentelekomcloud-infra/identity-deploy.git', 'ssh_url': 'git@github.com:opentelekomcloud-infra/identity-deploy.git', 'clone_url': 'https://github.com/opentelekomcloud-infra/identity-deploy.git', 'svn_url': 'https://github.com/opentelekomcloud-infra/identity-deploy', 'homepage': '', 'size': 48, 'stargazers_count': 0, 'watchers_count': 0, 'language': None, 'has_issues': True, 'has_projects': False, 'has_downloads': True, 'has_wiki': False, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 1, 'license': {'key': 'apache-2.0', 'name': 'Apache License 2.0', 'spdx_id': 'Apache-2.0', 'url': 'https://api.github.com/licenses/apache-2.0', 'node_id': 'MDc6TGljZW5zZTI='}, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 1, 'watchers': 0, 'default_branch': 'main'}}, 'base': {'label': 'opentelekomcloud-infra:main', 'ref': 'main', 'sha': '9f3646c241294deb375d1375d017f42498e29b2c', 'user': {'login': 'opentelekomcloud-infra', 'id': 45656414, 'node_id': 'MDEyOk9yZ2FuaXphdGlvbjQ1NjU2NDE0', 'avatar_url': 'https://avatars.githubusercontent.com/u/45656414?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/opentelekomcloud-infra', 'html_url': 'https://github.com/opentelekomcloud-infra', 'followers_url': 'https://api.github.com/users/opentelekomcloud-infra/followers', 'following_url': 'https://api.github.com/users/opentelekomcloud-infra/following{/other_user}', 'gists_url': 'https://api.github.com/users/opentelekomcloud-infra/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/opentelekomcloud-infra/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/opentelekomcloud-infra/subscriptions', 'organizations_url': 'https://api.github.com/users/opentelekomcloud-infra/orgs', 'repos_url': 'https://api.github.com/users/opentelekomcloud-infra/repos', 'events_url': 'https://api.github.com/users/opentelekomcloud-infra/events{/privacy}', 'received_events_url': 'https://api.github.com/users/opentelekomcloud-infra/received_events', 'type': 'Organization', 'site_admin': False}, 'repo': {'id': 438200218, 'node_id': 'R_kgDOGh5nmg', 'name': 'identity-deploy', 'full_name': 'opentelekomcloud-infra/identity-deploy', 'private': False, 'owner': {'login': 'opentelekomcloud-infra', 'id': 45656414, 'node_id': 'MDEyOk9yZ2FuaXphdGlvbjQ1NjU2NDE0', 'avatar_url': 'https://avatars.githubusercontent.com/u/45656414?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/opentelekomcloud-infra', 'html_url': 'https://github.com/opentelekomcloud-infra', 'followers_url': 'https://api.github.com/users/opentelekomcloud-infra/followers', 'following_url': 'https://api.github.com/users/opentelekomcloud-infra/following{/other_user}', 'gists_url': 'https://api.github.com/users/opentelekomcloud-infra/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/opentelekomcloud-infra/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/opentelekomcloud-infra/subscriptions', 'organizations_url': 'https://api.github.com/users/opentelekomcloud-infra/orgs', 'repos_url': 'https://api.github.com/users/opentelekomcloud-infra/repos', 'events_url': 'https://api.github.com/users/opentelekomcloud-infra/events{/privacy}', 'received_events_url': 'https://api.github.com/users/opentelekomcloud-infra/received_events', 'type': 'Organization', 'site_admin': False}, 'html_url': 'https://github.com/opentelekomcloud-infra/identity-deploy', 'description': 'Ansible playbook to deploy stand-alone OpenStack keystone service', 'fork': True, 'url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy', 'forks_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/forks', 'keys_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/teams', 'hooks_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/hooks', 'issue_events_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/events{/number}', 'events_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/events', 'assignees_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/assignees{/user}', 'branches_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/branches{/branch}', 'tags_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/tags', 'blobs_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/languages', 'stargazers_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/stargazers', 'contributors_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/contributors', 'subscribers_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/subscribers', 'subscription_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/subscription', 'commits_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/contents/{+path}', 'compare_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/merges', 'archive_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/downloads', 'issues_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues{/number}', 'pulls_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/labels{/name}', 'releases_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/releases{/id}', 'deployments_url': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/deployments', 'created_at': '2021-12-14T09:55:15Z', 'updated_at': '2021-12-29T10:33:01Z', 'pushed_at': '2022-02-02T14:20:41Z', 'git_url': 'git://github.com/opentelekomcloud-infra/identity-deploy.git', 'ssh_url': 'git@github.com:opentelekomcloud-infra/identity-deploy.git', 'clone_url': 'https://github.com/opentelekomcloud-infra/identity-deploy.git', 'svn_url': 'https://github.com/opentelekomcloud-infra/identity-deploy', 'homepage': '', 'size': 48, 'stargazers_count': 0, 'watchers_count': 0, 'language': None, 'has_issues': True, 'has_projects': False, 'has_downloads': True, 'has_wiki': False, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 1, 'license': {'key': 'apache-2.0', 'name': 'Apache License 2.0', 'spdx_id': 'Apache-2.0', 'url': 'https://api.github.com/licenses/apache-2.0', 'node_id': 'MDc6TGljZW5zZTI='}, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 1, 'watchers': 0, 'default_branch': 'main'}}, '_links': {'self': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16'}, 'html': {'href': 'https://github.com/opentelekomcloud-infra/identity-deploy/pull/16'}, 'issue': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/16'}, 'comments': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/issues/16/comments'}, 'review_comments': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16/comments'}, 'review_comment': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/comments{/number}'}, 'commits': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/pulls/16/commits'}, 'statuses': {'href': 'https://api.github.com/repos/opentelekomcloud-infra/identity-deploy/statuses/3673ec03da18e60a697368ef16d28c4b89e54228'}}, 'author_association': 'MEMBER', 'auto_merge': None, 'active_lock_reason': None}}, 'public': True, 'created_at': '2022-02-02T14:23:31Z', 'org': {'id': 45656414, 'login': 'opentelekomcloud-infra', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/opentelekomcloud-infra', 'avatar_url': 'https://avatars.githubusercontent.com/u/45656414?'}}, {'id': '20038546650', 'type': 'PushEvent', 'actor': {'id': 41898282, 'login': 'github-actions[bot]', 'display_login': 'github-actions', 'gravatar_id': '', 'url': 'https://api.github.com/users/github-actions[bot]', 'avatar_url': 'https://avatars.githubusercontent.com/u/41898282?'}, 'repo': {'id': 340782702, 'name': 'jasoncartwright/bbcrss', 'url': 'https://api.github.com/repos/jasoncartwright/bbcrss'}, 'payload': {'push_id': 8993439229, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/main', 'head': 'b6e924e03a85ef8e57fbd32ae19e815ccaec4ece', 'before': '7f96899e2f2e368f21a0899e87e6454d6bd172d5', 'commits': [{'sha': 'b6e924e03a85ef8e57fbd32ae19e815ccaec4ece', 'author': {'email': 'actions@users.noreply.github.com', 'name': 'Automated'}, 'message': 'Latest RSS: Wed Feb 2 14:23:29 UTC 2022', 'distinct': True, 'url': 'https://api.github.com/repos/jasoncartwright/bbcrss/commits/b6e924e03a85ef8e57fbd32ae19e815ccaec4ece'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546315', 'type': 'PushEvent', 'actor': {'id': 34437496, 'login': 'DanielPDWalker', 'display_login': 'DanielPDWalker', 'gravatar_id': '', 'url': 'https://api.github.com/users/DanielPDWalker', 'avatar_url': 'https://avatars.githubusercontent.com/u/34437496?'}, 'repo': {'id': 436636451, 'name': 'Matatika/dbt-tap-meltano', 'url': 'https://api.github.com/repos/Matatika/dbt-tap-meltano'}, 'payload': {'push_id': 8993439045, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/master', 'head': '2d6ba880189ba8507dd890bc015939df87ad2f2d', 'before': '6d8d1f6f5a310cf5e9258dc079c2dd2baaaaa24c', 'commits': [{'sha': '2d6ba880189ba8507dd890bc015939df87ad2f2d', 'author': {'email': 'danielpdwalker@gmail.com', 'name': 'danielpdwalker'}, 'message': 'Bumped version to 0.1.1', 'distinct': True, 'url': 'https://api.github.com/repos/Matatika/dbt-tap-meltano/commits/2d6ba880189ba8507dd890bc015939df87ad2f2d'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z', 'org': {'id': 63709023, 'login': 'Matatika', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/Matatika', 'avatar_url': 'https://avatars.githubusercontent.com/u/63709023?'}}, {'id': '20038546613', 'type': 'CreateEvent', 'actor': {'id': 13369065, 'login': 'appinlet', 'display_login': 'appinlet', 'gravatar_id': '', 'url': 'https://api.github.com/users/appinlet', 'avatar_url': 'https://avatars.githubusercontent.com/u/13369065?'}, 'repo': {'id': 215828308, 'name': 'DPO-Group/DPO_WooCommerce', 'url': 'https://api.github.com/repos/DPO-Group/DPO_WooCommerce'}, 'payload': {'ref': 'v1.1.1', 'ref_type': 'tag', 'master_branch': 'master', 'description': 'This is the DPO Group plugin for WooCommerce.', 'pusher_type': 'user'}, 'public': True, 'created_at': '2022-02-02T14:23:31Z', 'org': {'id': 55230053, 'login': 'DPO-Group', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/DPO-Group', 'avatar_url': 'https://avatars.githubusercontent.com/u/55230053?'}}, {'id': '20038545409', 'type': 'ForkEvent', 'actor': {'id': 71681815, 'login': 'LaudateCorpus1', 'display_login': 'LaudateCorpus1', 'gravatar_id': '', 'url': 'https://api.github.com/users/LaudateCorpus1', 'avatar_url': 'https://avatars.githubusercontent.com/u/71681815?'}, 'repo': {'id': 42317389, 'name': 'discord/node-spellchecker', 'url': 'https://api.github.com/repos/discord/node-spellchecker'}, 'payload': {'forkee': {'id': 454805289, 'node_id': 'R_kgDOGxvHKQ', 'name': 'node-spellchecker', 'full_name': 'LaudateCorpus1/node-spellchecker', 'private': False, 'owner': {'login': 'LaudateCorpus1', 'id': 71681815, 'node_id': 'MDQ6VXNlcjcxNjgxODE1', 'avatar_url': 'https://avatars.githubusercontent.com/u/71681815?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/LaudateCorpus1', 'html_url': 'https://github.com/LaudateCorpus1', 'followers_url': 'https://api.github.com/users/LaudateCorpus1/followers', 'following_url': 'https://api.github.com/users/LaudateCorpus1/following{/other_user}', 'gists_url': 'https://api.github.com/users/LaudateCorpus1/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/LaudateCorpus1/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/LaudateCorpus1/subscriptions', 'organizations_url': 'https://api.github.com/users/LaudateCorpus1/orgs', 'repos_url': 'https://api.github.com/users/LaudateCorpus1/repos', 'events_url': 'https://api.github.com/users/LaudateCorpus1/events{/privacy}', 'received_events_url': 'https://api.github.com/users/LaudateCorpus1/received_events', 'type': 'User', 'site_admin': False}, 'html_url': 'https://github.com/LaudateCorpus1/node-spellchecker', 'description': 'SpellChecker Node Module', 'fork': True, 'url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker', 'forks_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/forks', 'keys_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/keys{/key_id}', 'collaborators_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/collaborators{/collaborator}', 'teams_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/teams', 'hooks_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/hooks', 'issue_events_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/issues/events{/number}', 'events_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/events', 'assignees_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/assignees{/user}', 'branches_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/branches{/branch}', 'tags_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/tags', 'blobs_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/git/blobs{/sha}', 'git_tags_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/git/tags{/sha}', 'git_refs_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/git/refs{/sha}', 'trees_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/git/trees{/sha}', 'statuses_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/statuses/{sha}', 'languages_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/languages', 'stargazers_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/stargazers', 'contributors_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/contributors', 'subscribers_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/subscribers', 'subscription_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/subscription', 'commits_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/commits{/sha}', 'git_commits_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/git/commits{/sha}', 'comments_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/comments{/number}', 'issue_comment_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/issues/comments{/number}', 'contents_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/contents/{+path}', 'compare_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/compare/{base}...{head}', 'merges_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/merges', 'archive_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/{archive_format}{/ref}', 'downloads_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/downloads', 'issues_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/issues{/number}', 'pulls_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/pulls{/number}', 'milestones_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/milestones{/number}', 'notifications_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/notifications{?since,all,participating}', 'labels_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/labels{/name}', 'releases_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/releases{/id}', 'deployments_url': 'https://api.github.com/repos/LaudateCorpus1/node-spellchecker/deployments', 'created_at': '2022-02-02T14:23:24Z', 'updated_at': '2021-04-28T21:28:49Z', 'pushed_at': '2019-07-31T22:56:22Z', 'git_url': 'git://github.com/LaudateCorpus1/node-spellchecker.git', 'ssh_url': 'git@github.com:LaudateCorpus1/node-spellchecker.git', 'clone_url': 'https://github.com/LaudateCorpus1/node-spellchecker.git', 'svn_url': 'https://github.com/LaudateCorpus1/node-spellchecker', 'homepage': 'http://atom.github.io/node-spellchecker', 'size': 2623, 'stargazers_count': 0, 'watchers_count': 0, 'language': None, 'has_issues': False, 'has_projects': True, 'has_downloads': True, 'has_wiki': True, 'has_pages': False, 'forks_count': 0, 'mirror_url': None, 'archived': False, 'disabled': False, 'open_issues_count': 0, 'license': {'key': 'mit', 'name': 'MIT License', 'spdx_id': 'MIT', 'url': 'https://api.github.com/licenses/mit', 'node_id': 'MDc6TGljZW5zZTEz'}, 'allow_forking': True, 'is_template': False, 'topics': [], 'visibility': 'public', 'forks': 0, 'open_issues': 0, 'watchers': 0, 'default_branch': 'master', 'public': True}}, 'public': True, 'created_at': '2022-02-02T14:23:27Z', 'org': {'id': 1965106, 'login': 'discord', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/discord', 'avatar_url': 'https://avatars.githubusercontent.com/u/1965106?'}}, {'id': '20038546576', 'type': 'PushEvent', 'actor': {'id': 20691392, 'login': 'beckymarques', 'display_login': 'beckymarques', 'gravatar_id': '', 'url': 'https://api.github.com/users/beckymarques', 'avatar_url': 'https://avatars.githubusercontent.com/u/20691392?'}, 'repo': {'id': 445614110, 'name': 'colmeiaperformance/revitta', 'url': 'https://api.github.com/repos/colmeiaperformance/revitta'}, 'payload': {'push_id': 8993439091, 'size': 2, 'distinct_size': 0, 'ref': 'refs/heads/acf-php', 'head': 'e797634ff1538109056e51b1f221c6e2d49cef44', 'before': '53676bd520529cb7a2cb56d5b17d87a96ff624df', 'commits': [{'sha': 'e843b82907ca47ca26bf72643dc439e18721c448', 'author': {'email': 'brunarafaelav@outlook.com', 'name': 'brunarafaela'}, 'message': 'Add form style', 'distinct': False, 'url': 'https://api.github.com/repos/colmeiaperformance/revitta/commits/e843b82907ca47ca26bf72643dc439e18721c448'}, {'sha': 'e797634ff1538109056e51b1f221c6e2d49cef44', 'author': {'email': 'becky.marques@colmeiaperformance.com.br', 'name': 'Becky Marques'}, 'message': 'Update page-home.php', 'distinct': False, 'url': 'https://api.github.com/repos/colmeiaperformance/revitta/commits/e797634ff1538109056e51b1f221c6e2d49cef44'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z', 'org': {'id': 60509413, 'login': 'colmeiaperformance', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/colmeiaperformance', 'avatar_url': 'https://avatars.githubusercontent.com/u/60509413?'}}, {'id': '20038546558', 'type': 'CreateEvent', 'actor': {'id': 95173046, 'login': 'Guigzouz', 'display_login': 'Guigzouz', 'gravatar_id': '', 'url': 'https://api.github.com/users/Guigzouz', 'avatar_url': 'https://avatars.githubusercontent.com/u/95173046?'}, 'repo': {'id': 454804844, 'name': 'Guigzouz/Guigzouz', 'url': 'https://api.github.com/repos/Guigzouz/Guigzouz'}, 'payload': {'ref': 'main', 'ref_type': 'branch', 'master_branch': 'main', 'description': 'Config files for my GitHub profile.', 'pusher_type': 'user'}, 'public': True, 'created_at': '2022-02-02T14:23:30Z'}, {'id': '20038545401', 'type': 'PushEvent', 'actor': {'id': 70335472, 'login': 'FinnMal', 'display_login': 'FinnMal', 'gravatar_id': '', 'url': 'https://api.github.com/users/FinnMal', 'avatar_url': 'https://avatars.githubusercontent.com/u/70335472?'}, 'repo': {'id': 454804237, 'name': 'FinnMal/CryptopusBrowserGame', 'url': 'https://api.github.com/repos/FinnMal/CryptopusBrowserGame'}, 'payload': {'push_id': 8993438553, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/master', 'head': '93cf7c05835388799137a7f4d49dd7fce9b9f6da', 'before': 'bfd488bca2c4681abd88148ae60bce66a2b98993', 'commits': [{'sha': '93cf7c05835388799137a7f4d49dd7fce9b9f6da', 'author': {'email': 'finn@malkus.de', 'name': 'Finn Malkus'}, 'message': 'removed useless comments', 'distinct': True, 'url': 'https://api.github.com/repos/FinnMal/CryptopusBrowserGame/commits/93cf7c05835388799137a7f4d49dd7fce9b9f6da'}]}, 'public': True, 'created_at': '2022-02-02T14:23:27Z'}, {'id': '20038546574', 'type': 'PushEvent', 'actor': {'id': 55398995, 'login': 'Josh-Cena', 'display_login': 'Josh-Cena', 'gravatar_id': '', 'url': 'https://api.github.com/users/Josh-Cena', 'avatar_url': 'https://avatars.githubusercontent.com/u/55398995?'}, 'repo': {'id': 94911145, 'name': 'facebook/docusaurus', 'url': 'https://api.github.com/repos/facebook/docusaurus'}, 'payload': {'push_id': 8993439048, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/jc/read-category-metadata-aot', 'head': 'c81aee461f8ee44be5f4e1a4c960c1c1f9183850', 'before': 'a8f80488dff7f97023c1ca8f1d5d4d052c0ab3ce', 'commits': [{'sha': 'c81aee461f8ee44be5f4e1a4c960c1c1f9183850', 'author': {'email': 'sidachen2003@gmail.com', 'name': 'Joshua Chen'}, 'message': 'fix Windows...', 'distinct': True, 'url': 'https://api.github.com/repos/facebook/docusaurus/commits/c81aee461f8ee44be5f4e1a4c960c1c1f9183850'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z', 'org': {'id': 69631, 'login': 'facebook', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/facebook', 'avatar_url': 'https://avatars.githubusercontent.com/u/69631?'}}, {'id': '20038546549', 'type': 'PushEvent', 'actor': {'id': 88927411, 'login': 'pKorsholm', 'display_login': 'pKorsholm', 'gravatar_id': '', 'url': 'https://api.github.com/users/pKorsholm', 'avatar_url': 'https://avatars.githubusercontent.com/u/88927411?'}, 'repo': {'id': 271286876, 'name': 'medusajs/admin', 'url': 'https://api.github.com/repos/medusajs/admin'}, 'payload': {'push_id': 8993439042, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/feat/revamp', 'head': '6f2f2f0dcc04e97fb9b8a0242618b262a4ae3fcf', 'before': '8da6d03f865e0f8cdb3c1b7550585f8d67881f5a', 'commits': [{'sha': '6f2f2f0dcc04e97fb9b8a0242618b262a4ae3fcf', 'author': {'email': '88927411+pKorsholm@users.noreply.github.com', 'name': 'Philip Korsholm'}, 'message': 'Feat/revamp rma request return (#273)\n\n* progress on new components\r\n\r\n* progress\r\n\r\n* added responsive denomination grid\r\n\r\n* changed to molecule\r\n\r\n* progress\r\n\r\n* requested changes\r\n\r\n* update\r\n\r\n* fixed currencies\r\n\r\n* added new component to region settings + minor fixes to settings and story\r\n\r\n* requested changes\r\n\r\n* fixed story\r\n\r\n* removed comment\r\n\r\n* fix type\r\n\r\n* fix merge conflicts\r\n\r\n* initial returns modal\r\n\r\n* update create return modal\r\n\r\n* hotfix currency input\r\n\r\n* remove comments and console.logs\r\n\r\n* add shipping total\r\n\r\n* refactor return request rma\r\n\r\n* typescript cleanup\r\n\r\n* receive menu\r\n\r\n* remove unused button for selecting return reason\r\n\r\n* add select product table\r\n\r\n* switch to object based "toReturn" instead of array to accomodate extension with return reasons\r\n\r\n* create sub modal functionality\r\n\r\n* modal update for sub modal\r\n\r\n* animations config\r\n\r\n* layered modal\r\n\r\n* reset screens on close\r\n\r\n* final touches on select return reason\r\n\r\n* pr feedback\r\n\r\n* use hooks for request return\r\n\r\n* upgrade admin hooks\r\n\r\n* fix reason selection\r\n\r\nCo-authored-by: Kasper <kasper@medusa-commerce.com>\r\nCo-authored-by: olivermrbl <oliver@mrbltech.com>', 'distinct': True, 'url': 'https://api.github.com/repos/medusajs/admin/commits/6f2f2f0dcc04e97fb9b8a0242618b262a4ae3fcf'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z', 'org': {'id': 62591822, 'login': 'medusajs', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/medusajs', 'avatar_url': 'https://avatars.githubusercontent.com/u/62591822?'}}, {'id': '20038546598', 'type': 'PushEvent', 'actor': {'id': 67910697, 'login': 'cablemp5', 'display_login': 'cablemp5', 'gravatar_id': '', 'url': 'https://api.github.com/users/cablemp5', 'avatar_url': 'https://avatars.githubusercontent.com/u/67910697?'}, 'repo': {'id': 454228778, 'name': 'cablemp5/wordlebutshit', 'url': 'https://api.github.com/repos/cablemp5/wordlebutshit'}, 'payload': {'push_id': 8993439100, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/main', 'head': '9f66c5dc17b9e9609e698731a5e75ba3dbe1bae0', 'before': '2469e23be7a96ee7c3c59ec7af0dc416656fd36f', 'commits': [{'sha': '9f66c5dc17b9e9609e698731a5e75ba3dbe1bae0', 'author': {'email': 'cmikec12@gmail.com', 'name': 'Caleb Collins'}, 'message': 'Update README.md', 'distinct': True, 'url': 'https://api.github.com/repos/cablemp5/wordlebutshit/commits/9f66c5dc17b9e9609e698731a5e75ba3dbe1bae0'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546568', 'type': 'PushEvent', 'actor': {'id': 41898282, 'login': 'github-actions[bot]', 'display_login': 'github-actions', 'gravatar_id': '', 'url': 'https://api.github.com/users/github-actions[bot]', 'avatar_url': 'https://avatars.githubusercontent.com/u/41898282?'}, 'repo': {'id': 436332813, 'name': 'gdlcf88/gdlcf88', 'url': 'https://api.github.com/repos/gdlcf88/gdlcf88'}, 'payload': {'push_id': 8993439187, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/main', 'head': '11ff7aac50ad43a3fade75d97aead8b11a75a5d1', 'before': 'eaf23e20ccff80bc19cd3bbc0b17967b9d8c51a9', 'commits': [{'sha': '11ff7aac50ad43a3fade75d97aead8b11a75a5d1', 'author': {'email': '41898282+github-actions[bot]@users.noreply.github.com', 'name': 'github-actions[bot]'}, 'message': 'Update github-metrics.svg - [Skip GitHub Action]', 'distinct': True, 'url': 'https://api.github.com/repos/gdlcf88/gdlcf88/commits/11ff7aac50ad43a3fade75d97aead8b11a75a5d1'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z'}, {'id': '20038546464', 'type': 'IssueCommentEvent', 'actor': {'id': 1526295, 'login': 'sldblog', 'display_login': 'sldblog', 'gravatar_id': '', 'url': 'https://api.github.com/users/sldblog', 'avatar_url': 'https://avatars.githubusercontent.com/u/1526295?'}, 'repo': {'id': 312544484, 'name': 'ministryofjustice/hmpps-interventions-ui', 'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui'}, 'payload': {'action': 'created', 'issue': {'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197', 'repository_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui', 'labels_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/labels{/name}', 'comments_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/comments', 'events_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/events', 'html_url': 'https://github.com/ministryofjustice/hmpps-interventions-ui/issues/1197', 'id': 1117364167, 'node_id': 'I_kwDOEqEM5M5CmZ_H', 'number': 1197, 'title': 'A branch protection setting is not enabled: Include administrators', 'user': {'login': 'AntonyBishop', 'id': 36888942, 'node_id': 'MDQ6VXNlcjM2ODg4OTQy', 'avatar_url': 'https://avatars.githubusercontent.com/u/36888942?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/AntonyBishop', 'html_url': 'https://github.com/AntonyBishop', 'followers_url': 'https://api.github.com/users/AntonyBishop/followers', 'following_url': 'https://api.github.com/users/AntonyBishop/following{/other_user}', 'gists_url': 'https://api.github.com/users/AntonyBishop/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/AntonyBishop/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/AntonyBishop/subscriptions', 'organizations_url': 'https://api.github.com/users/AntonyBishop/orgs', 'repos_url': 'https://api.github.com/users/AntonyBishop/repos', 'events_url': 'https://api.github.com/users/AntonyBishop/events{/privacy}', 'received_events_url': 'https://api.github.com/users/AntonyBishop/received_events', 'type': 'User', 'site_admin': False}, 'labels': [], 'state': 'closed', 'locked': False, 'assignee': None, 'assignees': [], 'milestone': None, 'comments': 1, 'created_at': '2022-01-28T12:45:33Z', 'updated_at': '2022-02-02T14:23:29Z', 'closed_at': '2022-02-02T14:23:29Z', 'author_association': 'NONE', 'active_lock_reason': None, 'body': 'Hi there\nThe default branch protection setting called Include administrators is not enabled for this repository\nSee repository settings/Branches/Branch protection rules\nEither add a new Branch protection rule or edit the existing branch protection rule and select the Include administrators option\nThis will enable the branch protection rules to admin uses as well\nSee the repository standards: https://github.com/ministryofjustice/github-repository-standards\nSee the report: https://operations-engineering-reports.cloud-platform.service.justice.gov.uk/github_repositories\nPlease contact Operations Engineering on Slack #ask-operations-engineering, if you need any assistance\n', 'reactions': {'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/reactions', 'total_count': 0, '+1': 0, '-1': 0, 'laugh': 0, 'hooray': 0, 'confused': 0, 'heart': 0, 'rocket': 0, 'eyes': 0}, 'timeline_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197/timeline', 'performed_via_github_app': None}, 'comment': {'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/comments/1027990260', 'html_url': 'https://github.com/ministryofjustice/hmpps-interventions-ui/issues/1197#issuecomment-1027990260', 'issue_url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/1197', 'id': 1027990260, 'node_id': 'IC_kwDOEqEM5M49ReL0', 'user': {'login': 'sldblog', 'id': 1526295, 'node_id': 'MDQ6VXNlcjE1MjYyOTU=', 'avatar_url': 'https://avatars.githubusercontent.com/u/1526295?v=4', 'gravatar_id': '', 'url': 'https://api.github.com/users/sldblog', 'html_url': 'https://github.com/sldblog', 'followers_url': 'https://api.github.com/users/sldblog/followers', 'following_url': 'https://api.github.com/users/sldblog/following{/other_user}', 'gists_url': 'https://api.github.com/users/sldblog/gists{/gist_id}', 'starred_url': 'https://api.github.com/users/sldblog/starred{/owner}{/repo}', 'subscriptions_url': 'https://api.github.com/users/sldblog/subscriptions', 'organizations_url': 'https://api.github.com/users/sldblog/orgs', 'repos_url': 'https://api.github.com/users/sldblog/repos', 'events_url': 'https://api.github.com/users/sldblog/events{/privacy}', 'received_events_url': 'https://api.github.com/users/sldblog/received_events', 'type': 'User', 'site_admin': False}, 'created_at': '2022-02-02T14:23:29Z', 'updated_at': '2022-02-02T14:23:29Z', 'author_association': 'MEMBER', 'body': 'Done (feature/* branches)', 'reactions': {'url': 'https://api.github.com/repos/ministryofjustice/hmpps-interventions-ui/issues/comments/1027990260/reactions', 'total_count': 0, '+1': 0, '-1': 0, 'laugh': 0, 'hooray': 0, 'confused': 0, 'heart': 0, 'rocket': 0, 'eyes': 0}, 'performed_via_github_app': None}}, 'public': True, 'created_at': '2022-02-02T14:23:30Z', 'org': {'id': 2203574, 'login': 'ministryofjustice', 'gravatar_id': '', 'url': 'https://api.github.com/orgs/ministryofjustice', 'avatar_url': 'https://avatars.githubusercontent.com/u/2203574?'}}, {'id': '20038546609', 'type': 'PushEvent', 'actor': {'id': 43445963, 'login': 'paullaster', 'display_login': 'paullaster', 'gravatar_id': '', 'url': 'https://api.github.com/users/paullaster', 'avatar_url': 'https://avatars.githubusercontent.com/u/43445963?'}, 'repo': {'id': 454802080, 'name': 'paullaster/eclectics-ecommerce', 'url': 'https://api.github.com/repos/paullaster/eclectics-ecommerce'}, 'payload': {'push_id': 8993439093, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/master', 'head': '37eff08041baba364101159f50dd18b2f102b96d', 'before': 'c6a2880e0fb9b486c942b523ae5911e63dd72395', 'commits': [{'sha': '37eff08041baba364101159f50dd18b2f102b96d', 'author': {'email': 'paullasterokoth98@gmail.com', 'name': 'paullaster'}, 'message': 'Eclectics-ecommerce SPA initial commit', 'distinct': True, 'url': 'https://api.github.com/repos/paullaster/eclectics-ecommerce/commits/37eff08041baba364101159f50dd18b2f102b96d'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546607', 'type': 'PushEvent', 'actor': {'id': 92793982, 'login': 'natali177', 'display_login': 'natali177', 'gravatar_id': '', 'url': 'https://api.github.com/users/natali177', 'avatar_url': 'https://avatars.githubusercontent.com/u/92793982?'}, 'repo': {'id': 454686191, 'name': 'natali177/neoflex', 'url': 'https://api.github.com/repos/natali177/neoflex'}, 'payload': {'push_id': 8993439103, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/master', 'head': '78cb35bbad12f668d1eaa8379a6ffab89383c4ce', 'before': 'e655ff597cfdd2f54dae26695b30eb62c0f0d3a7', 'commits': [{'sha': '78cb35bbad12f668d1eaa8379a6ffab89383c4ce', 'author': {'email': 'nati_177@mail.ru', 'name': 'natali177'}, 'message': 'commit schema', 'distinct': True, 'url': 'https://api.github.com/repos/natali177/neoflex/commits/78cb35bbad12f668d1eaa8379a6ffab89383c4ce'}]}, 'public': True, 'created_at': '2022-02-02T14:23:31Z'}, {'id': '20038546441', 'type': 'PushEvent', 'actor': {'id': 3955124, 'login': 'Raicuparta', 'display_login': 'Raicuparta', 'gravatar_id': '', 'url': 'https://api.github.com/users/Raicuparta', 'avatar_url': 'https://avatars.githubusercontent.com/u/3955124?'}, 'repo': {'id': 435823157, 'name': 'Raicuparta/outerwildsmods.com', 'url': 'https://api.github.com/repos/Raicuparta/outerwildsmods.com'}, 'payload': {'push_id': 8993439128, 'size': 1, 'distinct_size': 1, 'ref': 'refs/heads/gh-pages', 'head': '7ca9f5f0c746629b25d6cc0a8846cbffafd2be5a', 'before': 'a6ff170e65bd0f68871cf0f95c472f1a1172d6ad', 'commits': [{'sha': '7ca9f5f0c746629b25d6cc0a8846cbffafd2be5a', 'author': {'email': 'Outer Wilds Mods Website', 'name': 'Outer Wilds Mods Website'}, 'message': 'Deploying to gh-pages from @ Raicuparta/outerwildsmods.com@e5734e6fa6761bd82f3fbfc9f8ac3ecf441ba5bd 🚀', 'distinct': True, 'url': 'https://api.github.com/repos/Raicuparta/outerwildsmods.com/commits/7ca9f5f0c746629b25d6cc0a8846cbffafd2be5a'}]}, 'public': True, 'created_at': '2022-02-02T14:23:30Z'}]
import pandas as pd
df = pd.DataFrame.from_dict(r.json())
df.groupby('type')['id'].count()
type CreateEvent 4 ForkEvent 2 IssueCommentEvent 1 IssuesEvent 1 PullRequestEvent 1 PullRequestReviewEvent 2 PushEvent 19 Name: id, dtype: int64
Exercice¶
- Add a new item in your navigation menu named
Sentiment Classifier - When the user select this item, a textbox is shown where our user can write a tweet and get its sentiment.
Bonus¶
Objectives of the day:
- DATA APP
- Live coding your ~first~ second (and third if we have time) complete data app:
- Reproducing the NY Uber ride analysis
- Creating a NLP as a service
- Live coding your ~first~ second (and third if we have time) complete data app:
References¶
- Streamlit API references: https://docs.streamlit.io/library/api-reference
- https://github.com/beingCurious/books#python
df.columns
import nltk
from nltk.corpus import stopwords
from nltk.tokenize import wordpunct_tokenize
import pandas as pd
df = pd.read_csv('../data/tweet-sentiment-withDay.csv')
series_tweets = df['text']
tweet_str = series_tweets.str.cat(sep = ' ')
list_of_words = [i.lower() for i in wordpunct_tokenize(tweet_str) if i.lower() not in stop and i.isalpha()]
wordfreqdist = nltk.FreqDist(list_of_words)
mostcommon = wordfreqdist.most_common(30)
print(mostcommon)
import pickle
from sklearn.ensemble import RandomForestRegressor
def train_model():
paris_data = pd.read_csv('../data/ParisHousing.csv')
feature_names = ['squareMeters', 'numberOfRooms', 'hasYard', 'hasPool', 'floors',
'numPrevOwners', 'made', 'isNewBuilt', 'hasStormProtector',
'basement', 'attic', 'garage', 'hasStorageRoom', 'hasGuestRoom']
target_name = ['price']
X = pd.DataFrame(paris_data, columns=feature_names)
Y = pd.DataFrame(paris_data, columns=target_name)
# Build Regression Model
model = RandomForestRegressor()
model.fit(X, Y.ravel())
return model
price_model =train_model()
filename = '../data/price_model.sav'
pickle.dump(price_model, open(filename, 'wb'))
data_json = {"squareMeters":{"0":0.0},"numberOfRooms":{"0":1},"hasYard":{"0":False},"hasPool":{"0":False},"floors":{"0":1},"numPrevOwners":{"0":10},"made":{"0":2021.0},"isNewBuilt":{"0":False},"hasStormProtector":{"0":True},"basement":{"0":0.0},"attic":{"0":0.1},"garage":{"0":0.0},"hasStorageRoom":{"0":False},"hasGuestRoom":{"0":True}}
df = pd.DataFrame(data=data_json)
df.head()